summaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'cpu')
-rw-r--r--cpu/SConscript167
-rw-r--r--cpu/activity.cc155
-rw-r--r--cpu/activity.hh124
-rw-r--r--cpu/base.cc378
-rw-r--r--cpu/base.hh238
-rw-r--r--cpu/base_dyn_inst.cc450
-rw-r--r--cpu/base_dyn_inst.hh738
-rw-r--r--cpu/checker/cpu.cc757
-rw-r--r--cpu/checker/cpu.hh347
-rw-r--r--cpu/checker/cpu_builder.cc156
-rw-r--r--cpu/checker/exec_context.hh266
-rw-r--r--cpu/checker/o3_cpu_builder.cc156
-rw-r--r--cpu/cpu_exec_context.cc315
-rw-r--r--cpu/cpu_exec_context.hh524
-rw-r--r--cpu/cpu_models.py80
-rw-r--r--cpu/exec_context.hh382
-rw-r--r--cpu/exetrace.cc231
-rw-r--r--cpu/exetrace.hh189
-rw-r--r--cpu/inst_seq.hh42
-rw-r--r--cpu/intr_control.cc97
-rw-r--r--cpu/intr_control.hh58
-rw-r--r--cpu/memtest/memtest.cc441
-rw-r--r--cpu/memtest/memtest.hh156
-rw-r--r--cpu/o3/2bit_local_pred.cc143
-rw-r--r--cpu/o3/2bit_local_pred.hh109
-rw-r--r--cpu/o3/alpha_cpu.cc36
-rw-r--r--cpu/o3/alpha_cpu.hh518
-rw-r--r--cpu/o3/alpha_cpu_builder.cc420
-rw-r--r--cpu/o3/alpha_cpu_impl.hh782
-rw-r--r--cpu/o3/alpha_dyn_inst.cc34
-rw-r--r--cpu/o3/alpha_dyn_inst.hh276
-rw-r--r--cpu/o3/alpha_dyn_inst_impl.hh182
-rw-r--r--cpu/o3/alpha_impl.hh80
-rw-r--r--cpu/o3/alpha_params.hh186
-rw-r--r--cpu/o3/bpred_unit.cc37
-rw-r--r--cpu/o3/bpred_unit.hh254
-rw-r--r--cpu/o3/bpred_unit_impl.hh410
-rw-r--r--cpu/o3/btb.cc134
-rw-r--r--cpu/o3/btb.hh127
-rw-r--r--cpu/o3/comm.hh196
-rw-r--r--cpu/o3/commit.cc33
-rw-r--r--cpu/o3/commit.hh456
-rw-r--r--cpu/o3/commit_impl.hh1308
-rw-r--r--cpu/o3/cpu.cc1183
-rw-r--r--cpu/o3/cpu.hh540
-rw-r--r--cpu/o3/cpu_policy.hh117
-rw-r--r--cpu/o3/decode.cc33
-rw-r--r--cpu/o3/decode.hh295
-rw-r--r--cpu/o3/decode_impl.hh750
-rw-r--r--cpu/o3/dep_graph.hh235
-rw-r--r--cpu/o3/fetch.cc33
-rw-r--r--cpu/o3/fetch.hh428
-rw-r--r--cpu/o3/fetch_impl.hh1221
-rw-r--r--cpu/o3/free_list.cc70
-rw-r--r--cpu/o3/free_list.hh189
-rw-r--r--cpu/o3/fu_pool.cc297
-rw-r--r--cpu/o3/fu_pool.hh165
-rw-r--r--cpu/o3/iew.cc34
-rw-r--r--cpu/o3/iew.hh522
-rw-r--r--cpu/o3/iew_impl.hh1587
-rw-r--r--cpu/o3/inst_queue.cc34
-rw-r--r--cpu/o3/inst_queue.hh501
-rw-r--r--cpu/o3/inst_queue_impl.hh1402
-rw-r--r--cpu/o3/lsq.cc36
-rw-r--r--cpu/o3/lsq.hh323
-rw-r--r--cpu/o3/lsq_impl.hh538
-rw-r--r--cpu/o3/lsq_unit.cc36
-rw-r--r--cpu/o3/lsq_unit.hh641
-rw-r--r--cpu/o3/lsq_unit_impl.hh878
-rw-r--r--cpu/o3/mem_dep_unit.cc46
-rw-r--r--cpu/o3/mem_dep_unit.hh262
-rw-r--r--cpu/o3/mem_dep_unit_impl.hh555
-rw-r--r--cpu/o3/ras.cc82
-rw-r--r--cpu/o3/ras.hh95
-rw-r--r--cpu/o3/regfile.hh266
-rw-r--r--cpu/o3/rename.cc33
-rw-r--r--cpu/o3/rename.hh470
-rw-r--r--cpu/o3/rename_impl.hh1281
-rw-r--r--cpu/o3/rename_map.cc245
-rw-r--r--cpu/o3/rename_map.hh166
-rw-r--r--cpu/o3/rob.cc34
-rw-r--r--cpu/o3/rob.hh317
-rw-r--r--cpu/o3/rob_impl.hh691
-rw-r--r--cpu/o3/sat_counter.hh113
-rw-r--r--cpu/o3/scoreboard.cc106
-rw-r--r--cpu/o3/scoreboard.hh114
-rw-r--r--cpu/o3/store_set.cc345
-rw-r--r--cpu/o3/store_set.hh145
-rw-r--r--cpu/o3/thread_state.hh143
-rw-r--r--cpu/o3/tournament_pred.cc291
-rw-r--r--cpu/o3/tournament_pred.hh216
-rw-r--r--cpu/ozone/back_end.cc5
-rw-r--r--cpu/ozone/back_end.hh516
-rw-r--r--cpu/ozone/back_end_impl.hh1904
-rw-r--r--cpu/ozone/cpu.cc34
-rw-r--r--cpu/ozone/cpu.hh629
-rw-r--r--cpu/ozone/cpu_builder.cc861
-rw-r--r--cpu/ozone/cpu_impl.hh1049
-rw-r--r--cpu/ozone/dyn_inst.cc35
-rw-r--r--cpu/ozone/dyn_inst.hh231
-rw-r--r--cpu/ozone/dyn_inst_impl.hh315
-rw-r--r--cpu/ozone/ea_list.cc77
-rw-r--r--cpu/ozone/ea_list.hh72
-rw-r--r--cpu/ozone/front_end.cc7
-rw-r--r--cpu/ozone/front_end.hh284
-rw-r--r--cpu/ozone/front_end_impl.hh920
-rw-r--r--cpu/ozone/inorder_back_end.cc5
-rw-r--r--cpu/ozone/inorder_back_end.hh450
-rw-r--r--cpu/ozone/inorder_back_end_impl.hh519
-rw-r--r--cpu/ozone/inst_queue.cc36
-rw-r--r--cpu/ozone/inst_queue.hh506
-rw-r--r--cpu/ozone/inst_queue_impl.hh1341
-rw-r--r--cpu/ozone/lsq_unit.cc34
-rw-r--r--cpu/ozone/lsq_unit.hh637
-rw-r--r--cpu/ozone/lsq_unit_impl.hh846
-rw-r--r--cpu/ozone/lw_back_end.cc5
-rw-r--r--cpu/ozone/lw_back_end.hh473
-rw-r--r--cpu/ozone/lw_back_end_impl.hh1693
-rw-r--r--cpu/ozone/lw_lsq.cc34
-rw-r--r--cpu/ozone/lw_lsq.hh657
-rw-r--r--cpu/ozone/lw_lsq_impl.hh874
-rw-r--r--cpu/ozone/null_predictor.hh76
-rw-r--r--cpu/ozone/ozone_impl.hh75
-rw-r--r--cpu/ozone/rename_table.cc7
-rw-r--r--cpu/ozone/rename_table.hh53
-rw-r--r--cpu/ozone/rename_table_impl.hh23
-rw-r--r--cpu/ozone/simple_impl.hh69
-rw-r--r--cpu/ozone/simple_params.hh191
-rw-r--r--cpu/ozone/thread_state.hh194
-rw-r--r--cpu/pc_event.cc155
-rw-r--r--cpu/pc_event.hh143
-rw-r--r--cpu/profile.cc155
-rw-r--r--cpu/profile.hh89
-rw-r--r--cpu/quiesce_event.cc20
-rw-r--r--cpu/quiesce_event.hh23
-rw-r--r--cpu/simple/cpu.cc955
-rw-r--r--cpu/simple/cpu.hh363
-rw-r--r--cpu/smt.hh59
-rw-r--r--cpu/static_inst.cc74
-rw-r--r--cpu/static_inst.hh475
-rw-r--r--cpu/thread_state.hh129
-rw-r--r--cpu/trace/opt_cpu.cc239
-rw-r--r--cpu/trace/opt_cpu.hh223
-rw-r--r--cpu/trace/reader/ibm_reader.cc120
-rw-r--r--cpu/trace/reader/ibm_reader.hh73
-rw-r--r--cpu/trace/reader/itx_reader.cc206
-rw-r--r--cpu/trace/reader/itx_reader.hh84
-rw-r--r--cpu/trace/reader/m5_reader.cc97
-rw-r--r--cpu/trace/reader/m5_reader.hh67
-rw-r--r--cpu/trace/reader/mem_trace_reader.cc37
-rw-r--r--cpu/trace/reader/mem_trace_reader.hh57
-rw-r--r--cpu/trace/trace_cpu.cc179
-rw-r--r--cpu/trace/trace_cpu.hh140
153 files changed, 0 insertions, 50171 deletions
diff --git a/cpu/SConscript b/cpu/SConscript
deleted file mode 100644
index 3840b9d41..000000000
--- a/cpu/SConscript
+++ /dev/null
@@ -1,167 +0,0 @@
-# -*- mode:python -*-
-
-# Copyright (c) 2006 The Regents of The University of Michigan
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-import os
-import os.path
-
-# Import build environment variable from SConstruct.
-Import('env')
-
-#################################################################
-#
-# Generate StaticInst execute() method signatures.
-#
-# There must be one signature for each CPU model compiled in.
-# Since the set of compiled-in models is flexible, we generate a
-# header containing the appropriate set of signatures on the fly.
-#
-#################################################################
-
-# CPU model-specific data is contained in cpu_models.py
-# Convert to SCons File node to get path handling
-models_db = File('cpu_models.py')
-# slurp in contents of file
-execfile(models_db.srcnode().abspath)
-
-# Template for execute() signature.
-exec_sig_template = '''
-virtual Fault execute(%s *xc, Trace::InstRecord *traceData) const = 0;
-'''
-
-mem_ini_sig_template = '''
-virtual Fault initiateAcc(%s *xc, Trace::InstRecord *traceData) const { panic("Not defined!"); };
-'''
-
-mem_comp_sig_template = '''
-virtual Fault completeAcc(uint8_t *data, %s *xc, Trace::InstRecord *traceData) const { panic("Not defined!"); return NoFault; };
-'''
-
-# Generate header.
-def gen_cpu_exec_signatures(target, source, env):
- f = open(str(target[0]), 'w')
- print >> f, '''
-#ifndef __CPU_STATIC_INST_EXEC_SIGS_HH__
-#define __CPU_STATIC_INST_EXEC_SIGS_HH__
-'''
- for cpu in env['CPU_MODELS']:
- xc_type = CpuModel.dict[cpu].strings['CPU_exec_context']
- print >> f, exec_sig_template % xc_type
- print >> f, mem_ini_sig_template % xc_type
- print >> f, mem_comp_sig_template % xc_type
- print >> f, '''
-#endif // __CPU_STATIC_INST_EXEC_SIGS_HH__
-'''
-
-# Generate string that gets printed when header is rebuilt
-def gen_sigs_string(target, source, env):
- return "Generating static_inst_exec_sigs.hh: " \
- + ', '.join(env['CPU_MODELS'])
-
-# Add command to generate header to environment.
-env.Command('static_inst_exec_sigs.hh', models_db,
- Action(gen_cpu_exec_signatures, gen_sigs_string,
- varlist = ['CPU_MODELS']))
-
-#################################################################
-#
-# Include CPU-model-specific files based on set of models
-# specified in CPU_MODELS build option.
-#
-#################################################################
-
-sources = []
-
-if 'SimpleCPU' in env['CPU_MODELS']:
- sources += Split('simple/cpu.cc')
-
-if 'FastCPU' in env['CPU_MODELS']:
- sources += Split('fast/cpu.cc')
-
-if 'AlphaFullCPU' in env['CPU_MODELS']:
- sources += Split('''
- o3/2bit_local_pred.cc
- o3/alpha_dyn_inst.cc
- o3/alpha_cpu.cc
- o3/alpha_cpu_builder.cc
- o3/bpred_unit.cc
- o3/btb.cc
- o3/commit.cc
- o3/decode.cc
- o3/fetch.cc
- o3/free_list.cc
- o3/fu_pool.cc
- o3/cpu.cc
- o3/iew.cc
- o3/inst_queue.cc
- o3/lsq_unit.cc
- o3/lsq.cc
- o3/mem_dep_unit.cc
- o3/ras.cc
- o3/rename.cc
- o3/rename_map.cc
- o3/rob.cc
- o3/scoreboard.cc
- o3/store_set.cc
- o3/tournament_pred.cc
- ''')
-
-if 'OzoneSimpleCPU' in env['CPU_MODELS']:
- sources += Split('''
- ozone/cpu.cc
- ozone/cpu_builder.cc
- ozone/dyn_inst.cc
- ozone/front_end.cc
- ozone/inorder_back_end.cc
- ozone/inst_queue.cc
- ozone/rename_table.cc
- ''')
-
-if 'OzoneCPU' in env['CPU_MODELS']:
- sources += Split('''
- ozone/back_end.cc
- ozone/lsq_unit.cc
- ozone/lw_back_end.cc
- ozone/lw_lsq.cc
- ''')
-
-if 'CheckerCPU' in env['CPU_MODELS']:
- sources += Split('''
- checker/cpu.cc
- checker/cpu_builder.cc
- checker/o3_cpu_builder.cc
- ''')
-
-# FullCPU sources are included from m5/SConscript since they're not
-# below this point in the file hierarchy.
-
-# Convert file names to SCons File objects. This takes care of the
-# path relative to the top of the directory tree.
-sources = [File(s) for s in sources]
-
-Return('sources')
-
diff --git a/cpu/activity.cc b/cpu/activity.cc
deleted file mode 100644
index b0b16446c..000000000
--- a/cpu/activity.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "base/timebuf.hh"
-#include "cpu/activity.hh"
-
-ActivityRecorder::ActivityRecorder(int num_stages, int longest_latency,
- int activity)
- : activityBuffer(longest_latency, 0), longestLatency(longest_latency),
- activityCount(activity), numStages(num_stages)
-{
- stageActive = new bool[numStages];
- memset(stageActive, 0, numStages);
-}
-
-void
-ActivityRecorder::activity()
-{
- // If we've already recorded activity for this cycle, we don't
- // want to increment the count any more.
- if (activityBuffer[0]) {
- return;
- }
-
- activityBuffer[0] = true;
-
- ++activityCount;
-
- DPRINTF(Activity, "Activity: %i\n", activityCount);
-}
-
-void
-ActivityRecorder::advance()
-{
- // If there's a 1 in the slot that is about to be erased once the
- // time buffer advances, then decrement the activityCount.
- if (activityBuffer[-longestLatency]) {
- --activityCount;
-
- assert(activityCount >= 0);
-
- DPRINTF(Activity, "Activity: %i\n", activityCount);
-
- if (activityCount == 0) {
- DPRINTF(Activity, "No activity left!\n");
- }
- }
-
- activityBuffer.advance();
-}
-
-void
-ActivityRecorder::activateStage(const int idx)
-{
- // Increment the activity count if this stage wasn't already active.
- if (!stageActive[idx]) {
- ++activityCount;
-
- stageActive[idx] = true;
-
- DPRINTF(Activity, "Activity: %i\n", activityCount);
- } else {
- DPRINTF(Activity, "Stage %i already active.\n", idx);
- }
-
-// assert(activityCount < longestLatency + numStages + 1);
-}
-
-void
-ActivityRecorder::deactivateStage(const int idx)
-{
- // Decrement the activity count if this stage was active.
- if (stageActive[idx]) {
- --activityCount;
-
- stageActive[idx] = false;
-
- DPRINTF(Activity, "Activity: %i\n", activityCount);
- } else {
- DPRINTF(Activity, "Stage %i already inactive.\n", idx);
- }
-
- assert(activityCount >= 0);
-}
-
-void
-ActivityRecorder::reset()
-{
- activityCount = 0;
- memset(stageActive, 0, numStages);
- for (int i = 0; i < longestLatency + 1; ++i)
- activityBuffer.advance();
-}
-
-void
-ActivityRecorder::dump()
-{
- for (int i = 0; i <= longestLatency; ++i) {
- cprintf("[Idx:%i %i] ", i, activityBuffer[-i]);
- }
-
- cprintf("\n");
-
- for (int i = 0; i < numStages; ++i) {
- cprintf("[Stage:%i %i]\n", i, stageActive[i]);
- }
-
- cprintf("\n");
-
- cprintf("Activity count: %i\n", activityCount);
-}
-
-void
-ActivityRecorder::validate()
-{
- int count = 0;
- for (int i = 0; i <= longestLatency; ++i) {
- if (activityBuffer[-i]) {
- count++;
- }
- }
-
- for (int i = 0; i < numStages; ++i) {
- if (stageActive[i]) {
- count++;
- }
- }
-
- assert(count == activityCount);
-}
diff --git a/cpu/activity.hh b/cpu/activity.hh
deleted file mode 100644
index 2c0df5efb..000000000
--- a/cpu/activity.hh
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_ACTIVITY_HH__
-#define __CPU_ACTIVITY_HH__
-
-#include "base/timebuf.hh"
-#include "base/trace.hh"
-
-/**
- * ActivityRecorder helper class that informs the CPU if it can switch
- * over to being idle or not. It works by having a time buffer as
- * long as any time buffer in the CPU, and the CPU and all of its
- * stages inform the ActivityRecorder when they write to any time
- * buffer. The ActivityRecorder marks a 1 in the "0" slot of the time
- * buffer any time a stage writes to a time buffer, and it advances
- * its time buffer at the same time as all other stages. The
- * ActivityRecorder also records if a stage has activity to do next
- * cycle. The recorder keeps a count of these two. Thus any time the
- * count is non-zero, there is either communication still in flight,
- * or activity that still must be done, meaning that the CPU can not
- * idle. If count is zero, then the CPU can safely idle as it has no
- * more outstanding work to do.
- */
-class ActivityRecorder {
- public:
- ActivityRecorder(int num_stages, int longest_latency, int count);
-
- /** Records that there is activity this cycle. */
- void activity();
-
- /** Advances the activity buffer, decrementing the activityCount
- * if active communication just left the time buffer, and
- * determining if there is no activity.
- */
- void advance();
-
- /** Marks a stage as active. */
- void activateStage(const int idx);
-
- /** Deactivates a stage. */
- void deactivateStage(const int idx);
-
- /** Returns how many things are active within the recorder. */
- int getActivityCount() { return activityCount; }
-
- /** Sets the count to a starting value. Can be used to disable
- * the idling option.
- */
- void setActivityCount(int count)
- { activityCount = count; }
-
- /** Returns if the CPU should be active. */
- bool active() { return activityCount; }
-
- /** Clears the time buffer and the activity count. */
- void reset();
-
- /** Debug function to dump the contents of the time buffer. */
- void dump();
-
- /** Debug function to ensure that the activity count matches the
- * contents of the time buffer.
- */
- void validate();
-
- private:
- /** Time buffer that tracks if any cycles has active communication
- * in them. It should be as long as the longest communication
- * latency in the system. Each time any time buffer is written,
- * the activity buffer should also be written to. The
- * activityBuffer is advanced along with all the other time
- * buffers, so it should have a 1 somewhere in it only if there
- * is active communication in a time buffer.
- */
- TimeBuffer<bool> activityBuffer;
-
- /** Longest latency time buffer in the CPU. */
- int longestLatency;
-
- /** Tracks how many stages and cycles of time buffer have
- * activity. Stages increment this count when they switch to
- * active, and decrement it when they switch to
- * inactive. Whenever a cycle that previously had no information
- * is written in the time buffer, this is incremented. When a
- * cycle that had information exits the time buffer due to age,
- * this count is decremented. When the count is 0, there is no
- * activity in the CPU, and it can be descheduled.
- */
- int activityCount;
-
- /** Number of stages that can be marked as active or inactive. */
- int numStages;
-
- /** Records which stages are active/inactive. */
- bool *stageActive;
-};
-
-#endif // __CPU_ACTIVITY_HH__
diff --git a/cpu/base.cc b/cpu/base.cc
deleted file mode 100644
index de03b9eab..000000000
--- a/cpu/base.cc
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <iostream>
-#include <string>
-#include <sstream>
-
-#include "base/cprintf.hh"
-#include "base/loader/symtab.hh"
-#include "base/misc.hh"
-#include "base/output.hh"
-#include "cpu/base.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/profile.hh"
-#include "cpu/sampler/sampler.hh"
-#include "sim/param.hh"
-#include "sim/process.hh"
-#include "sim/sim_events.hh"
-#include "sim/system.hh"
-
-#include "base/trace.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;
-
-#if FULL_SYSTEM
-BaseCPU::BaseCPU(Params *p)
- : SimObject(p->name), clock(p->clock), checkInterrupts(true),
- params(p), number_of_threads(p->numberOfThreads), system(p->system)
-#else
-BaseCPU::BaseCPU(Params *p)
- : SimObject(p->name), clock(p->clock), params(p),
- number_of_threads(p->numberOfThreads)
-#endif
-{
- DPRINTF(FullCPU, "BaseCPU: Creating object, mem address %#x.\n", this);
-
- // add self to global list of CPUs
- cpuList.push_back(this);
-
- DPRINTF(FullCPU, "BaseCPU: CPU added to cpuList, mem address %#x.\n",
- this);
-
- if (number_of_threads > maxThreadsPerCPU)
- maxThreadsPerCPU = number_of_threads;
-
- // allocate per-thread instruction-based event queues
- comInstEventQueue = new EventQueue *[number_of_threads];
- for (int i = 0; i < number_of_threads; ++i)
- comInstEventQueue[i] = new EventQueue("instruction-based event queue");
-
- //
- // set up instruction-count-based termination events, if any
- //
- if (p->max_insts_any_thread != 0)
- for (int i = 0; i < number_of_threads; ++i)
- new SimExitEvent(comInstEventQueue[i], p->max_insts_any_thread,
- "a thread reached the max instruction count");
-
- if (p->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(comInstEventQueue[i],
- "all threads reached the max instruction count",
- p->max_insts_all_threads, *counter);
- }
-
- // allocate per-thread load-based event queues
- comLoadEventQueue = new EventQueue *[number_of_threads];
- for (int i = 0; i < number_of_threads; ++i)
- comLoadEventQueue[i] = new EventQueue("load-based event queue");
-
- //
- // set up instruction-count-based termination events, if any
- //
- if (p->max_loads_any_thread != 0)
- for (int i = 0; i < number_of_threads; ++i)
- new SimExitEvent(comLoadEventQueue[i], p->max_loads_any_thread,
- "a thread reached the max load count");
-
- if (p->max_loads_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(comLoadEventQueue[i],
- "all threads reached the max load count",
- p->max_loads_all_threads, *counter);
- }
-
-#if FULL_SYSTEM
- memset(interrupts, 0, sizeof(interrupts));
- intstatus = 0;
-#endif
-
- functionTracingEnabled = false;
- if (p->functionTrace) {
- functionTraceStream = simout.find(csprintf("ftrace.%s", name()));
- currentFunctionStart = currentFunctionEnd = 0;
- functionEntryTick = p->functionTraceStart;
-
- if (p->functionTraceStart == 0) {
- functionTracingEnabled = true;
- } else {
- Event *e =
- new EventWrapper<BaseCPU, &BaseCPU::enableFunctionTrace>(this,
- true);
- e->schedule(p->functionTraceStart);
- }
- }
-#if FULL_SYSTEM
- profileEvent = NULL;
- if (params->profile)
- profileEvent = new ProfileEvent(this, params->profile);
-#endif
-
-}
-
-BaseCPU::Params::Params()
-{
-#if FULL_SYSTEM
- profile = false;
-#endif
- checker = NULL;
-}
-
-void
-BaseCPU::enableFunctionTrace()
-{
- functionTracingEnabled = true;
-}
-
-BaseCPU::~BaseCPU()
-{
-}
-
-void
-BaseCPU::init()
-{
- if (!params->deferRegistration)
- registerExecContexts();
-}
-
-void
-BaseCPU::startup()
-{
-#if FULL_SYSTEM
- if (!params->deferRegistration && profileEvent)
- profileEvent->schedule(curTick);
-#endif
-}
-
-
-void
-BaseCPU::regStats()
-{
- using namespace Stats;
-
- numCycles
- .name(name() + ".numCycles")
- .desc("number of cpu cycles simulated")
- ;
-
- int size = execContexts.size();
- if (size > 1) {
- for (int i = 0; i < size; ++i) {
- stringstream namestr;
- ccprintf(namestr, "%s.ctx%d", name(), i);
- execContexts[i]->regStats(namestr.str());
- }
- } else if (size == 1)
- execContexts[0]->regStats(name());
-
-#if FULL_SYSTEM
-#endif
-}
-
-
-void
-BaseCPU::registerExecContexts()
-{
- for (int i = 0; i < execContexts.size(); ++i) {
- ExecContext *xc = execContexts[i];
-
- if (xc->status() == ExecContext::Suspended) {
-#if FULL_SYSTEM
- int id = params->cpu_id;
- if (id != -1)
- id += i;
-
- xc->setCpuId(system->registerExecContext(xc, id));
-#else
- xc->setCpuId(xc->getProcessPtr()->registerExecContext(xc));
-#endif
- }
- }
-}
-
-
-void
-BaseCPU::switchOut(Sampler *sampler)
-{
- panic("This CPU doesn't support sampling!");
-}
-
-void
-BaseCPU::takeOverFrom(BaseCPU *oldCPU)
-{
- assert(execContexts.size() == oldCPU->execContexts.size());
-
- for (int i = 0; i < execContexts.size(); ++i) {
- ExecContext *newXC = execContexts[i];
- ExecContext *oldXC = oldCPU->execContexts[i];
-
- newXC->takeOverFrom(oldXC);
- assert(newXC->readCpuId() == oldXC->readCpuId());
-#if FULL_SYSTEM
- system->replaceExecContext(newXC, newXC->readCpuId());
-#else
- assert(newXC->getProcessPtr() == oldXC->getProcessPtr());
- newXC->getProcessPtr()->replaceExecContext(newXC, newXC->readCpuId());
-#endif
- }
-
-#if FULL_SYSTEM
- for (int i = 0; i < TheISA::NumInterruptLevels; ++i)
- interrupts[i] = oldCPU->interrupts[i];
- intstatus = oldCPU->intstatus;
-
- for (int i = 0; i < execContexts.size(); ++i)
- execContexts[i]->profileClear();
-
- if (profileEvent)
- profileEvent->schedule(curTick);
-#endif
-}
-
-
-#if FULL_SYSTEM
-BaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, int _interval)
- : Event(&mainEventQueue), cpu(_cpu), interval(_interval)
-{ }
-
-void
-BaseCPU::ProfileEvent::process()
-{
- for (int i = 0, size = cpu->execContexts.size(); i < size; ++i) {
- ExecContext *xc = cpu->execContexts[i];
- xc->profileSample();
- }
-
- schedule(curTick + interval);
-}
-
-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 >= TheISA::NumInterruptLevels)
- panic("int_num out of bounds\n");
-
- if (index < 0 || index >= sizeof(uint64_t) * 8)
- panic("int_num out of bounds\n");
-
- checkInterrupts = true;
- 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 >= TheISA::NumInterruptLevels)
- panic("int_num out of bounds\n");
-
- if (index < 0 || index >= sizeof(uint64_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;
-}
-
-
-void
-BaseCPU::serialize(std::ostream &os)
-{
- SERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
- SERIALIZE_SCALAR(intstatus);
-}
-
-void
-BaseCPU::unserialize(Checkpoint *cp, const std::string &section)
-{
- UNSERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
- UNSERIALIZE_SCALAR(intstatus);
-}
-
-#endif // FULL_SYSTEM
-
-void
-BaseCPU::traceFunctionsInternal(Addr pc)
-{
- if (!debugSymbolTable)
- return;
-
- // if pc enters different function, print new function symbol and
- // update saved range. Otherwise do nothing.
- if (pc < currentFunctionStart || pc >= currentFunctionEnd) {
- string sym_str;
- bool found = debugSymbolTable->findNearestSymbol(pc, sym_str,
- currentFunctionStart,
- currentFunctionEnd);
-
- if (!found) {
- // no symbol found: use addr as label
- sym_str = csprintf("0x%x", pc);
- currentFunctionStart = pc;
- currentFunctionEnd = pc + 1;
- }
-
- ccprintf(*functionTraceStream, " (%d)\n%d: %s",
- curTick - functionEntryTick, curTick, sym_str);
- functionEntryTick = curTick;
- }
-}
-
-
-DEFINE_SIM_OBJECT_CLASS_NAME("BaseCPU", BaseCPU)
diff --git a/cpu/base.hh b/cpu/base.hh
deleted file mode 100644
index dd776859d..000000000
--- a/cpu/base.hh
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_BASE_HH__
-#define __CPU_BASE_HH__
-
-#include <vector>
-
-#include "base/statistics.hh"
-#include "config/full_system.hh"
-#include "cpu/sampler/sampler.hh"
-#include "sim/eventq.hh"
-#include "sim/sim_object.hh"
-#include "arch/isa_traits.hh"
-
-class BranchPred;
-class CheckerCPU;
-class ExecContext;
-class System;
-
-class BaseCPU : public SimObject
-{
- protected:
- // CPU's clock period in terms of the number of ticks of curTime.
- Tick clock;
-
- public:
- inline Tick frequency() const { return Clock::Frequency / clock; }
- inline Tick cycles(int numCycles) const { return clock * numCycles; }
- inline Tick curCycle() const { return curTick / clock; }
-
-#if FULL_SYSTEM
- protected:
- uint64_t interrupts[TheISA::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 checkInterrupts;
-
- bool check_interrupt(int int_num) const {
- if (int_num > TheISA::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; }
-
- class ProfileEvent : public Event
- {
- private:
- BaseCPU *cpu;
- int interval;
-
- public:
- ProfileEvent(BaseCPU *cpu, int interval);
- void process();
- };
- ProfileEvent *profileEvent;
-#endif
-
- protected:
- std::vector<ExecContext *> execContexts;
-
- public:
-
- /// Notify the CPU that the indicated context is now active. The
- /// delay parameter indicates the number of ticks to wait before
- /// executing (typically 0 or 1).
- virtual void activateContext(int thread_num, int delay) {}
-
- /// Notify the CPU that the indicated context is now suspended.
- virtual void suspendContext(int thread_num) {}
-
- /// Notify the CPU that the indicated context is now deallocated.
- virtual void deallocateContext(int thread_num) {}
-
- /// Notify the CPU that the indicated context is now halted.
- virtual void haltContext(int thread_num) {}
-
- public:
- struct Params
- {
- std::string name;
- int numberOfThreads;
- bool deferRegistration;
- Counter max_insts_any_thread;
- Counter max_insts_all_threads;
- Counter max_loads_any_thread;
- Counter max_loads_all_threads;
- Tick clock;
- bool functionTrace;
- Tick functionTraceStart;
-#if FULL_SYSTEM
- System *system;
- int cpu_id;
- Tick profile;
-#endif
- BaseCPU *checker;
-
- Params();
- };
-
- const Params *params;
-
- BaseCPU(Params *params);
- virtual ~BaseCPU();
-
- virtual void init();
- virtual void startup();
- virtual void regStats();
-
- virtual void activateWhenReady(int tid) {};
-
- void registerExecContexts();
-
- /// Prepare for another CPU to take over execution. When it is
- /// is ready (drained pipe) it signals the sampler.
- virtual void switchOut(Sampler *);
-
- /// Take over execution from the given CPU. Used for warm-up and
- /// sampling.
- virtual void takeOverFrom(BaseCPU *);
-
- /**
- * 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 **comInstEventQueue;
-
- /**
- * Vector of per-thread load-based event queues. Used for
- * scheduling events based on number of loads committed by
- *a particular thread.
- */
- EventQueue **comLoadEventQueue;
-
-#if FULL_SYSTEM
- System *system;
-
- /**
- * Serialize this object to the given output stream.
- * @param os The stream to serialize to.
- */
- virtual void serialize(std::ostream &os);
-
- /**
- * Reconstruct the state of this object from a checkpoint.
- * @param cp The checkpoint use.
- * @param section The section name of this object
- */
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-
-#endif
-
- /**
- * Return pointer to CPU's branch predictor (NULL if none).
- * @return Branch predictor pointer.
- */
- virtual BranchPred *getBranchPred() { return NULL; };
-
- virtual Counter totalInstructions() const { return 0; }
-
- // Function tracing
- private:
- bool functionTracingEnabled;
- std::ostream *functionTraceStream;
- Addr currentFunctionStart;
- Addr currentFunctionEnd;
- Tick functionEntryTick;
- void enableFunctionTrace();
- void traceFunctionsInternal(Addr pc);
-
- protected:
- void traceFunctions(Addr pc)
- {
- if (functionTracingEnabled)
- traceFunctionsInternal(pc);
- }
-
- private:
- static std::vector<BaseCPU *> cpuList; //!< Static global cpu list
-
- public:
- static int numSimulatedCPUs() { return cpuList.size(); }
- static Counter numSimulatedInstructions()
- {
- Counter total = 0;
-
- int size = cpuList.size();
- for (int i = 0; i < size; ++i)
- total += cpuList[i]->totalInstructions();
-
- return total;
- }
-
- public:
- // Number of CPU cycles simulated
- Stats::Scalar<> numCycles;
-};
-
-#endif // __CPU_BASE_HH__
diff --git a/cpu/base_dyn_inst.cc b/cpu/base_dyn_inst.cc
deleted file mode 100644
index 64a995689..000000000
--- a/cpu/base_dyn_inst.cc
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <iostream>
-#include <set>
-#include <string>
-#include <sstream>
-
-#include "base/cprintf.hh"
-#include "base/trace.hh"
-
-#include "arch/faults.hh"
-#include "cpu/exetrace.hh"
-#include "mem/mem_req.hh"
-
-#include "cpu/base_dyn_inst.hh"
-#include "cpu/o3/alpha_impl.hh"
-#include "cpu/o3/alpha_cpu.hh"
-#include "cpu/ozone/simple_impl.hh"
-#include "cpu/ozone/ozone_impl.hh"
-
-using namespace std;
-using namespace TheISA;
-
-#define NOHASH
-#ifndef NOHASH
-
-#include "base/hashmap.hh"
-
-unsigned int MyHashFunc(const BaseDynInst *addr)
-{
- unsigned a = (unsigned)addr;
- unsigned hash = (((a >> 14) ^ ((a >> 2) & 0xffff))) & 0x7FFFFFFF;
-
- return hash;
-}
-
-typedef m5::hash_map<const BaseDynInst *, const BaseDynInst *, MyHashFunc>
-my_hash_t;
-
-my_hash_t thishash;
-#endif
-
-template <class Impl>
-BaseDynInst<Impl>::BaseDynInst(ExtMachInst machInst, Addr inst_PC,
- Addr pred_PC, InstSeqNum seq_num,
- FullCPU *cpu)
- : staticInst(machInst), traceData(NULL), cpu(cpu)/*, xc(cpu->xcBase())*/
-{
- seqNum = seq_num;
-
- PC = inst_PC;
- nextPC = PC + sizeof(MachInst);
- predPC = pred_PC;
-
- initVars();
-}
-
-template <class Impl>
-BaseDynInst<Impl>::BaseDynInst(StaticInstPtr &_staticInst)
- : staticInst(_staticInst), traceData(NULL)
-{
- seqNum = 0;
- initVars();
-}
-
-template <class Impl>
-void
-BaseDynInst<Impl>::initVars()
-{
- req = NULL;
- effAddr = MemReq::inval_addr;
- physEffAddr = MemReq::inval_addr;
- storeSize = 0;
-
- readyRegs = 0;
-
- completed = false;
- resultReady = false;
- canIssue = false;
- issued = false;
- executed = false;
- canCommit = false;
- committed = false;
- squashed = false;
- squashedInIQ = false;
- squashedInLSQ = false;
- squashedInROB = false;
- eaCalcDone = false;
- memOpDone = false;
- lqIdx = -1;
- sqIdx = -1;
- reachedCommit = false;
-
- blockingInst = false;
- recoverInst = false;
-
- iqEntry = false;
- robEntry = false;
-
- serializeBefore = false;
- serializeAfter = false;
- serializeHandled = false;
-
- // Eventually make this a parameter.
- threadNumber = 0;
-
- // Also make this a parameter, or perhaps get it from xc or cpu.
- asid = 0;
-
- // Initialize the fault to be unimplemented opcode.
-// fault = new UnimplementedOpcodeFault;
- fault = NoFault;
-
- ++instcount;
-
- if (instcount > 1500) {
- cpu->dumpInsts();
-#ifdef DEBUG
- dumpSNList();
-#endif
- assert(instcount <= 1500);
- }
-
- DPRINTF(DynInst, "DynInst: [sn:%lli] Instruction created. Instcount=%i\n",
- seqNum, instcount);
-
-#ifdef DEBUG
- cpu->snList.insert(seqNum);
-#endif
-}
-
-template <class Impl>
-BaseDynInst<Impl>::~BaseDynInst()
-{
- if (req) {
- req = NULL;
- }
-
- if (traceData) {
- delete traceData;
- }
-
- fault = NoFault;
-
- --instcount;
-
- DPRINTF(DynInst, "DynInst: [sn:%lli] Instruction destroyed. Instcount=%i\n",
- seqNum, instcount);
-#ifdef DEBUG
- cpu->snList.erase(seqNum);
-#endif
-}
-
-#ifdef DEBUG
-template <class Impl>
-void
-BaseDynInst<Impl>::dumpSNList()
-{
- std::set<InstSeqNum>::iterator sn_it = cpu->snList.begin();
-
- int count = 0;
- while (sn_it != cpu->snList.end()) {
- cprintf("%i: [sn:%lli] not destroyed\n", count, (*sn_it));
- count++;
- sn_it++;
- }
-}
-#endif
-
-template <class Impl>
-void
-BaseDynInst<Impl>::prefetch(Addr addr, unsigned flags)
-{
- // This is the "functional" implementation of prefetch. Not much
- // happens here since prefetches don't affect the architectural
- // state.
-
- // Generate a MemReq so we can translate the effective address.
- MemReqPtr req = new MemReq(addr, thread->getXCProxy(), 1, flags);
- req->asid = asid;
-
- // Prefetches never cause faults.
- fault = NoFault;
-
- // note this is a local, not BaseDynInst::fault
- Fault trans_fault = cpu->translateDataReadReq(req);
-
- if (trans_fault == NoFault && !(req->flags & UNCACHEABLE)) {
- // It's a valid address to cacheable space. Record key MemReq
- // parameters so we can generate another one just like it for
- // the timing access without calling translate() again (which
- // might mess up the TLB).
- effAddr = req->vaddr;
- physEffAddr = req->paddr;
- memReqFlags = req->flags;
- } else {
- // Bogus address (invalid or uncacheable space). Mark it by
- // setting the eff_addr to InvalidAddr.
- effAddr = physEffAddr = MemReq::inval_addr;
- }
-
- if (traceData) {
- traceData->setAddr(addr);
- }
-}
-
-template <class Impl>
-void
-BaseDynInst<Impl>::writeHint(Addr addr, int size, unsigned flags)
-{
- // Need to create a MemReq here so we can do a translation. This
- // will casue a TLB miss trap if necessary... not sure whether
- // that's the best thing to do or not. We don't really need the
- // MemReq otherwise, since wh64 has no functional effect.
- MemReqPtr req = new MemReq(addr, thread->getXCProxy(), size, flags);
- req->asid = asid;
-
- fault = cpu->translateDataWriteReq(req);
-
- if (fault == NoFault && !(req->flags & UNCACHEABLE)) {
- // Record key MemReq parameters so we can generate another one
- // just like it for the timing access without calling translate()
- // again (which might mess up the TLB).
- effAddr = req->vaddr;
- physEffAddr = req->paddr;
- memReqFlags = req->flags;
- } else {
- // ignore faults & accesses to uncacheable space... treat as no-op
- effAddr = physEffAddr = MemReq::inval_addr;
- }
-
- storeSize = size;
- storeData = 0;
-}
-
-/**
- * @todo Need to find a way to get the cache block size here.
- */
-template <class Impl>
-Fault
-BaseDynInst<Impl>::copySrcTranslate(Addr src)
-{
- MemReqPtr req = new MemReq(src, thread->getXCProxy(), 64);
- req->asid = asid;
-
- // translate to physical address
- Fault fault = cpu->translateDataReadReq(req);
-
- if (fault == NoFault) {
- thread->copySrcAddr = src;
- thread->copySrcPhysAddr = req->paddr;
- } else {
- thread->copySrcAddr = 0;
- thread->copySrcPhysAddr = 0;
- }
- return fault;
-}
-
-/**
- * @todo Need to find a way to get the cache block size here.
- */
-template <class Impl>
-Fault
-BaseDynInst<Impl>::copy(Addr dest)
-{
- uint8_t data[64];
- FunctionalMemory *mem = thread->mem;
- assert(thread->copySrcPhysAddr);
- MemReqPtr req = new MemReq(dest, thread->getXCProxy(), 64);
- req->asid = asid;
-
- // translate to physical address
- Fault fault = cpu->translateDataWriteReq(req);
-
- if (fault == NoFault) {
- Addr dest_addr = req->paddr;
- // Need to read straight from memory since we have more than 8 bytes.
- req->paddr = thread->copySrcPhysAddr;
- mem->read(req, data);
- req->paddr = dest_addr;
- mem->write(req, data);
- }
- return fault;
-}
-
-template <class Impl>
-void
-BaseDynInst<Impl>::dump()
-{
- cprintf("T%d : %#08d `", threadNumber, PC);
- cout << staticInst->disassemble(PC);
- cprintf("'\n");
-}
-
-template <class Impl>
-void
-BaseDynInst<Impl>::dump(std::string &outstring)
-{
- std::ostringstream s;
- s << "T" << threadNumber << " : 0x" << PC << " "
- << staticInst->disassemble(PC);
-
- outstring = s.str();
-}
-
-#if 0
-template <class Impl>
-Fault
-BaseDynInst<Impl>::mem_access(mem_cmd cmd, Addr addr, void *p, int nbytes)
-{
- Fault fault;
-
- // check alignments, even speculative this test should always pass
- if ((nbytes & nbytes - 1) != 0 || (addr & nbytes - 1) != 0) {
- for (int i = 0; i < nbytes; i++)
- ((char *) p)[i] = 0;
-
- // I added the following because according to the comment above,
- // we should never get here. The comment lies
-#if 0
- panic("unaligned access. Cycle = %n", curTick);
-#endif
- return NoFault;
- }
-
- MemReqPtr req = new MemReq(addr, thread, nbytes);
- switch(cmd) {
- case Read:
- fault = spec_mem->read(req, (uint8_t *)p);
- break;
-
- case Write:
- fault = spec_mem->write(req, (uint8_t *)p);
- if (fault != NoFault)
- break;
-
- specMemWrite = true;
- storeSize = nbytes;
- switch(nbytes) {
- case sizeof(uint8_t):
- *(uint8_t)&storeData = (uint8_t *)p;
- break;
- case sizeof(uint16_t):
- *(uint16_t)&storeData = (uint16_t *)p;
- break;
- case sizeof(uint32_t):
- *(uint32_t)&storeData = (uint32_t *)p;
- break;
- case sizeof(uint64_t):
- *(uint64_t)&storeData = (uint64_t *)p;
- break;
- }
- break;
-
- default:
- fault = genMachineCheckFault();
- break;
- }
-
- trace_mem(fault, cmd, addr, p, nbytes);
-
- return fault;
-}
-
-#endif
-
-template <class Impl>
-void
-BaseDynInst<Impl>::markSrcRegReady()
-{
- if (++readyRegs == numSrcRegs()) {
- canIssue = true;
- }
-}
-
-template <class Impl>
-void
-BaseDynInst<Impl>::markSrcRegReady(RegIndex src_idx)
-{
- ++readyRegs;
-
- _readySrcRegIdx[src_idx] = true;
-
- if (readyRegs == numSrcRegs()) {
- canIssue = true;
- }
-}
-
-template <class Impl>
-bool
-BaseDynInst<Impl>::eaSrcsReady()
-{
- // For now I am assuming that src registers 1..n-1 are the ones that the
- // EA calc depends on. (i.e. src reg 0 is the source of the data to be
- // stored)
-
- for (int i = 1; i < numSrcRegs(); ++i) {
- if (!_readySrcRegIdx[i])
- return false;
- }
-
- return true;
-}
-
-// Forward declaration
-template class BaseDynInst<AlphaSimpleImpl>;
-
-template <>
-int
-BaseDynInst<AlphaSimpleImpl>::instcount = 0;
-
-// Forward declaration
-template class BaseDynInst<SimpleImpl>;
-
-template <>
-int
-BaseDynInst<SimpleImpl>::instcount = 0;
-
-// Forward declaration
-template class BaseDynInst<OzoneImpl>;
-
-template <>
-int
-BaseDynInst<OzoneImpl>::instcount = 0;
diff --git a/cpu/base_dyn_inst.hh b/cpu/base_dyn_inst.hh
deleted file mode 100644
index 388ea4a8d..000000000
--- a/cpu/base_dyn_inst.hh
+++ /dev/null
@@ -1,738 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_BASE_DYN_INST_HH__
-#define __CPU_BASE_DYN_INST_HH__
-
-#include <list>
-#include <string>
-
-#include "base/fast_alloc.hh"
-#include "base/trace.hh"
-#include "config/full_system.hh"
-#include "cpu/exetrace.hh"
-#include "cpu/inst_seq.hh"
-#include "cpu/static_inst.hh"
-#include "encumbered/cpu/full/op_class.hh"
-#include "mem/functional/memory_control.hh"
-#include "sim/system.hh"
-/*
-#include "encumbered/cpu/full/bpred_update.hh"
-#include "encumbered/cpu/full/spec_memory.hh"
-#include "encumbered/cpu/full/spec_state.hh"
-#include "encumbered/mem/functional/main.hh"
-*/
-
-/**
- * @file
- * Defines a dynamic instruction context.
- */
-
-// Forward declaration.
-class StaticInstPtr;
-
-template <class Impl>
-class BaseDynInst : public FastAlloc, public RefCounted
-{
- public:
- // Typedef for the CPU.
- typedef typename Impl::FullCPU FullCPU;
- typedef typename FullCPU::ImplState ImplState;
-
- // Binary machine instruction type.
- typedef TheISA::MachInst MachInst;
- // Extended machine instruction type
- typedef TheISA::ExtMachInst ExtMachInst;
- // Logical register index type.
- typedef TheISA::RegIndex RegIndex;
- // Integer register index type.
- typedef TheISA::IntReg IntReg;
-
- // The DynInstPtr type.
- typedef typename Impl::DynInstPtr DynInstPtr;
-
- // The list of instructions iterator type.
- typedef typename std::list<DynInstPtr>::iterator ListIt;
-
- enum {
- MaxInstSrcRegs = TheISA::MaxInstSrcRegs, /// Max source regs
- MaxInstDestRegs = TheISA::MaxInstDestRegs, /// Max dest regs
- };
-
- /** The StaticInst used by this BaseDynInst. */
- StaticInstPtr staticInst;
-
- ////////////////////////////////////////////
- //
- // INSTRUCTION EXECUTION
- //
- ////////////////////////////////////////////
- /** InstRecord that tracks this instructions. */
- Trace::InstRecord *traceData;
-
- /**
- * Does a read to a given address.
- * @param addr The address to read.
- * @param data The read's data is written into this parameter.
- * @param flags The request's flags.
- * @return Returns any fault due to the read.
- */
- template <class T>
- Fault read(Addr addr, T &data, unsigned flags);
-
- /**
- * Does a write to a given address.
- * @param data The data to be written.
- * @param addr The address to write to.
- * @param flags The request's flags.
- * @param res The result of the write (for load locked/store conditionals).
- * @return Returns any fault due to the write.
- */
- template <class T>
- Fault write(T data, Addr addr, unsigned flags,
- uint64_t *res);
-
- void prefetch(Addr addr, unsigned flags);
- void writeHint(Addr addr, int size, unsigned flags);
- Fault copySrcTranslate(Addr src);
- Fault copy(Addr dest);
-
- /** @todo: Consider making this private. */
- public:
- /** The sequence number of the instruction. */
- InstSeqNum seqNum;
-
- /** Is the instruction in the IQ */
- bool iqEntry;
-
- /** Is the instruction in the ROB */
- bool robEntry;
-
- /** Is the instruction in the LSQ */
- bool lsqEntry;
-
- /** Is the instruction completed. */
- bool completed;
-
- /** Is the instruction's result ready. */
- bool resultReady;
-
- /** Can this instruction issue. */
- bool canIssue;
-
- /** Has this instruction issued. */
- bool issued;
-
- /** Has this instruction executed (or made it through execute) yet. */
- bool executed;
-
- /** Can this instruction commit. */
- bool canCommit;
-
- /** Is this instruction committed. */
- bool committed;
-
- /** Is this instruction squashed. */
- bool squashed;
-
- /** Is this instruction squashed in the instruction queue. */
- bool squashedInIQ;
-
- /** Is this instruction squashed in the instruction queue. */
- bool squashedInLSQ;
-
- /** Is this instruction squashed in the instruction queue. */
- bool squashedInROB;
-
- /** Is this a recover instruction. */
- bool recoverInst;
-
- /** Is this a thread blocking instruction. */
- bool blockingInst; /* this inst has called thread_block() */
-
- /** Is this a thread syncrhonization instruction. */
- bool threadsyncWait;
-
- /** The thread this instruction is from. */
- short threadNumber;
-
- /** data address space ID, for loads & stores. */
- short asid;
-
- /** How many source registers are ready. */
- unsigned readyRegs;
-
- /** Pointer to the FullCPU object. */
- FullCPU *cpu;
-
- /** Pointer to the exec context. */
- ImplState *thread;
-
- /** The kind of fault this instruction has generated. */
- Fault fault;
-
- /** The memory request. */
- MemReqPtr req;
-
- /** The effective virtual address (lds & stores only). */
- Addr effAddr;
-
- /** The effective physical address. */
- Addr physEffAddr;
-
- /** Effective virtual address for a copy source. */
- Addr copySrcEffAddr;
-
- /** Effective physical address for a copy source. */
- Addr copySrcPhysEffAddr;
-
- /** The memory request flags (from translation). */
- unsigned memReqFlags;
-
- /** The size of the data to be stored. */
- int storeSize;
-
- /** The data to be stored. */
- IntReg storeData;
-
- union Result {
- uint64_t integer;
- float fp;
- double dbl;
- };
-
- /** The result of the instruction; assumes for now that there's only one
- * destination register.
- */
- Result instResult;
-
- /** PC of this instruction. */
- Addr PC;
-
- /** Next non-speculative PC. It is not filled in at fetch, but rather
- * once the target of the branch is truly known (either decode or
- * execute).
- */
- Addr nextPC;
-
- /** Predicted next PC. */
- Addr predPC;
-
- /** Count of total number of dynamic instructions. */
- static int instcount;
-
-#ifdef DEBUG
- void dumpSNList();
-#endif
-
- /** Whether or not the source register is ready.
- * @todo: Not sure this should be here vs the derived class.
- */
- bool _readySrcRegIdx[MaxInstSrcRegs];
-
- public:
- /** BaseDynInst constructor given a binary instruction.
- * @param inst The binary instruction.
- * @param PC The PC of the instruction.
- * @param pred_PC The predicted next PC.
- * @param seq_num The sequence number of the instruction.
- * @param cpu Pointer to the instruction's CPU.
- */
- BaseDynInst(ExtMachInst inst, Addr PC, Addr pred_PC, InstSeqNum seq_num,
- FullCPU *cpu);
-
- /** BaseDynInst constructor given a StaticInst pointer.
- * @param _staticInst The StaticInst for this BaseDynInst.
- */
- BaseDynInst(StaticInstPtr &_staticInst);
-
- /** BaseDynInst destructor. */
- ~BaseDynInst();
-
- private:
- /** Function to initialize variables in the constructors. */
- void initVars();
-
- public:
- /**
- * @todo: Make this function work; currently it is a dummy function.
- * @param fault Last fault.
- * @param cmd Last command.
- * @param addr Virtual address of access.
- * @param p Memory accessed.
- * @param nbytes Access size.
- */
- void
- trace_mem(Fault fault,
- MemCmd cmd,
- Addr addr,
- void *p,
- int nbytes);
-
- /** Dumps out contents of this BaseDynInst. */
- void dump();
-
- /** Dumps out contents of this BaseDynInst into given string. */
- void dump(std::string &outstring);
-
- /** Returns the fault type. */
- Fault getFault() { return fault; }
-
- /** Checks whether or not this instruction has had its branch target
- * calculated yet. For now it is not utilized and is hacked to be
- * always false.
- * @todo: Actually use this instruction.
- */
- bool doneTargCalc() { return false; }
-
- /** Returns the next PC. This could be the speculative next PC if it is
- * called prior to the actual branch target being calculated.
- */
- Addr readNextPC() { return nextPC; }
-
- /** Set the predicted target of this current instruction. */
- void setPredTarg(Addr predicted_PC) { predPC = predicted_PC; }
-
- /** Returns the predicted target of the branch. */
- Addr readPredTarg() { return predPC; }
-
- /** Returns whether the instruction was predicted taken or not. */
- bool predTaken() { return predPC != (PC + sizeof(MachInst)); }
-
- /** Returns whether the instruction mispredicted. */
- bool mispredicted() { return predPC != nextPC; }
-
- //
- // Instruction types. Forward checks to StaticInst object.
- //
- bool isNop() const { return staticInst->isNop(); }
- bool isMemRef() const { return staticInst->isMemRef(); }
- bool isLoad() const { return staticInst->isLoad(); }
- bool isStore() const { return staticInst->isStore(); }
- bool isStoreConditional() const
- { return staticInst->isStoreConditional(); }
- bool isInstPrefetch() const { return staticInst->isInstPrefetch(); }
- bool isDataPrefetch() const { return staticInst->isDataPrefetch(); }
- bool isCopy() const { return staticInst->isCopy(); }
- bool isInteger() const { return staticInst->isInteger(); }
- bool isFloating() const { return staticInst->isFloating(); }
- bool isControl() const { return staticInst->isControl(); }
- bool isCall() const { return staticInst->isCall(); }
- bool isReturn() const { return staticInst->isReturn(); }
- bool isDirectCtrl() const { return staticInst->isDirectCtrl(); }
- bool isIndirectCtrl() const { return staticInst->isIndirectCtrl(); }
- bool isCondCtrl() const { return staticInst->isCondCtrl(); }
- bool isUncondCtrl() const { return staticInst->isUncondCtrl(); }
- bool isThreadSync() const { return staticInst->isThreadSync(); }
- bool isSerializing() const { return staticInst->isSerializing(); }
- bool isSerializeBefore() const
- { return staticInst->isSerializeBefore() || serializeBefore; }
- bool isSerializeAfter() const
- { return staticInst->isSerializeAfter() || serializeAfter; }
- bool isMemBarrier() const { return staticInst->isMemBarrier(); }
- bool isWriteBarrier() const { return staticInst->isWriteBarrier(); }
- bool isNonSpeculative() const { return staticInst->isNonSpeculative(); }
- bool isQuiesce() const { return staticInst->isQuiesce(); }
- bool isIprAccess() const { return staticInst->isIprAccess(); }
- bool isUnverifiable() const { return staticInst->isUnverifiable(); }
-
- /** Temporarily sets this instruction as a serialize before instruction. */
- void setSerializeBefore() { serializeBefore = true; }
-
- /** Clears the serializeBefore part of this instruction. */
- void clearSerializeBefore() { serializeBefore = false; }
-
- /** Checks if this serializeBefore is only temporarily set. */
- bool isTempSerializeBefore() { return serializeBefore; }
-
- /** Tracks if instruction has been externally set as serializeBefore. */
- bool serializeBefore;
-
- /** Temporarily sets this instruction as a serialize after instruction. */
- void setSerializeAfter() { serializeAfter = true; }
-
- /** Clears the serializeAfter part of this instruction.*/
- void clearSerializeAfter() { serializeAfter = false; }
-
- /** Checks if this serializeAfter is only temporarily set. */
- bool isTempSerializeAfter() { return serializeAfter; }
-
- /** Tracks if instruction has been externally set as serializeAfter. */
- bool serializeAfter;
-
- /** Checks if the serialization part of this instruction has been
- * handled. This does not apply to the temporary serializing
- * state; it only applies to this instruction's own permanent
- * serializing state.
- */
- bool isSerializeHandled() { return serializeHandled; }
-
- /** Sets the serialization part of this instruction as handled. */
- void setSerializeHandled() { serializeHandled = true; }
-
- /** Whether or not the serialization of this instruction has been handled. */
- bool serializeHandled;
-
- /** Returns the opclass of this instruction. */
- OpClass opClass() const { return staticInst->opClass(); }
-
- /** Returns the branch target address. */
- Addr branchTarget() const { return staticInst->branchTarget(PC); }
-
- /** Returns the number of source registers. */
- int8_t numSrcRegs() const { return staticInst->numSrcRegs(); }
-
- /** Returns the number of destination registers. */
- int8_t numDestRegs() const { return staticInst->numDestRegs(); }
-
- // the following are used to track physical register usage
- // for machines with separate int & FP reg files
- int8_t numFPDestRegs() const { return staticInst->numFPDestRegs(); }
- int8_t numIntDestRegs() const { return staticInst->numIntDestRegs(); }
-
- /** Returns the logical register index of the i'th destination register. */
- RegIndex destRegIdx(int i) const { return staticInst->destRegIdx(i); }
-
- /** Returns the logical register index of the i'th source register. */
- RegIndex srcRegIdx(int i) const { return staticInst->srcRegIdx(i); }
-
- /** Returns the result of an integer instruction. */
- uint64_t readIntResult() { return instResult.integer; }
-
- /** Returns the result of a floating point instruction. */
- float readFloatResult() { return instResult.fp; }
-
- /** Returns the result of a floating point (double) instruction. */
- double readDoubleResult() { return instResult.dbl; }
-
- void setIntReg(const StaticInst *si, int idx, uint64_t val)
- {
- instResult.integer = val;
- }
-
- void setFloatRegSingle(const StaticInst *si, int idx, float val)
- {
- instResult.fp = val;
- }
-
- void setFloatRegDouble(const StaticInst *si, int idx, double val)
- {
- instResult.dbl = val;
- }
-
- void setFloatRegInt(const StaticInst *si, int idx, uint64_t val)
- {
- instResult.integer = val;
- }
-
- /** Records that one of the source registers is ready. */
- void markSrcRegReady();
-
- /** Marks a specific register as ready. */
- void markSrcRegReady(RegIndex src_idx);
-
- /** Returns if a source register is ready. */
- bool isReadySrcRegIdx(int idx) const
- {
- return this->_readySrcRegIdx[idx];
- }
-
- /** Sets this instruction as completed. */
- void setCompleted() { completed = true; }
-
- /** Returns whether or not this instruction is completed. */
- bool isCompleted() const { return completed; }
-
- void setResultReady() { resultReady = true; }
-
- bool isResultReady() const { return resultReady; }
-
- /** Sets this instruction as ready to issue. */
- void setCanIssue() { canIssue = true; }
-
- /** Returns whether or not this instruction is ready to issue. */
- bool readyToIssue() const { return canIssue; }
-
- /** Sets this instruction as issued from the IQ. */
- void setIssued() { issued = true; }
-
- /** Returns whether or not this instruction has issued. */
- bool isIssued() const { return issued; }
-
- /** Sets this instruction as executed. */
- void setExecuted() { executed = true; }
-
- /** Returns whether or not this instruction has executed. */
- bool isExecuted() const { return executed; }
-
- /** Sets this instruction as ready to commit. */
- void setCanCommit() { canCommit = true; }
-
- /** Clears this instruction as being ready to commit. */
- void clearCanCommit() { canCommit = false; }
-
- /** Returns whether or not this instruction is ready to commit. */
- bool readyToCommit() const { return canCommit; }
-
- /** Sets this instruction as committed. */
- void setCommitted() { committed = true; }
-
- /** Returns whether or not this instruction is committed. */
- bool isCommitted() const { return committed; }
-
- /** Sets this instruction as squashed. */
- void setSquashed() { squashed = true; }
-
- /** Returns whether or not this instruction is squashed. */
- bool isSquashed() const { return squashed; }
-
- //Instruction Queue Entry
- //-----------------------
- /** Sets this instruction as a entry the IQ. */
- void setInIQ() { iqEntry = true; }
-
- /** Sets this instruction as a entry the IQ. */
- void removeInIQ() { iqEntry = false; }
-
- /** Sets this instruction as squashed in the IQ. */
- void setSquashedInIQ() { squashedInIQ = true; squashed = true;}
-
- /** Returns whether or not this instruction is squashed in the IQ. */
- bool isSquashedInIQ() const { return squashedInIQ; }
-
- /** Returns whether or not this instruction has issued. */
- bool isInIQ() const { return iqEntry; }
-
-
- //Load / Store Queue Functions
- //-----------------------
- /** Sets this instruction as a entry the LSQ. */
- void setInLSQ() { lsqEntry = true; }
-
- /** Sets this instruction as a entry the LSQ. */
- void removeInLSQ() { lsqEntry = false; }
-
- /** Sets this instruction as squashed in the LSQ. */
- void setSquashedInLSQ() { squashedInLSQ = true;}
-
- /** Returns whether or not this instruction is squashed in the LSQ. */
- bool isSquashedInLSQ() const { return squashedInLSQ; }
-
- /** Returns whether or not this instruction is in the LSQ. */
- bool isInLSQ() const { return lsqEntry; }
-
-
- //Reorder Buffer Functions
- //-----------------------
- /** Sets this instruction as a entry the ROB. */
- void setInROB() { robEntry = true; }
-
- /** Sets this instruction as a entry the ROB. */
- void removeInROB() { robEntry = false; }
-
- /** Sets this instruction as squashed in the ROB. */
- void setSquashedInROB() { squashedInROB = true; }
-
- /** Returns whether or not this instruction is squashed in the ROB. */
- bool isSquashedInROB() const { return squashedInROB; }
-
- /** Returns whether or not this instruction is in the ROB. */
- bool isInROB() const { return robEntry; }
-
- /** Read the PC of this instruction. */
- const Addr readPC() const { return PC; }
-
- /** Set the next PC of this instruction (its actual target). */
- void setNextPC(uint64_t val)
- {
- nextPC = val;
-// instResult.integer = val;
- }
-
- void setASID(short addr_space_id) { asid = addr_space_id; }
-
- void setThread(unsigned tid) { threadNumber = tid; }
-
- void setState(ImplState *state) { thread = state; }
-
- /** Returns the exec context.
- * @todo: Remove this once the ExecContext is no longer used.
- */
- ExecContext *xcBase() { return thread->getXCProxy(); }
-
- private:
- /** Instruction effective address.
- * @todo: Consider if this is necessary or not.
- */
- Addr instEffAddr;
-
- /** Whether or not the effective address calculation is completed.
- * @todo: Consider if this is necessary or not.
- */
- bool eaCalcDone;
-
- public:
- /** Sets the effective address. */
- void setEA(Addr &ea) { instEffAddr = ea; eaCalcDone = true; }
-
- /** Returns the effective address. */
- const Addr &getEA() const { return req->vaddr; }
-
- /** Returns whether or not the eff. addr. calculation has been completed. */
- bool doneEACalc() { return eaCalcDone; }
-
- /** Returns whether or not the eff. addr. source registers are ready. */
- bool eaSrcsReady();
-
- /** Whether or not the memory operation is done. */
- bool memOpDone;
-
- public:
- /** Load queue index. */
- int16_t lqIdx;
-
- /** Store queue index. */
- int16_t sqIdx;
-
- bool reachedCommit;
-
- /** Iterator pointing to this BaseDynInst in the list of all insts. */
- ListIt instListIt;
-
- /** Returns iterator to this instruction in the list of all insts. */
- ListIt &getInstListIt() { return instListIt; }
-
- /** Sets iterator for this instruction in the list of all insts. */
- void setInstListIt(ListIt _instListIt) { instListIt = _instListIt; }
-};
-
-template<class Impl>
-template<class T>
-inline Fault
-BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
-{
- if (executed) {
- fault = cpu->read(req, data, lqIdx);
- return fault;
- }
-
- req = new MemReq(addr, thread->getXCProxy(), sizeof(T), flags);
- req->asid = asid;
- req->thread_num = threadNumber;
- req->pc = this->PC;
-
- if ((req->vaddr & (TheISA::VMPageSize - 1)) + req->size >
- TheISA::VMPageSize) {
- return TheISA::genAlignmentFault();
- }
-
- fault = cpu->translateDataReadReq(req);
-
- effAddr = req->vaddr;
- physEffAddr = req->paddr;
- memReqFlags = req->flags;
-
- if (fault == NoFault) {
-#if FULL_SYSTEM
- if (cpu->system->memctrl->badaddr(physEffAddr)) {
- fault = TheISA::genMachineCheckFault();
- data = (T)-1;
- this->setExecuted();
- } else {
- fault = cpu->read(req, data, lqIdx);
- }
-#else
- fault = cpu->read(req, data, lqIdx);
-#endif
- } else {
- // Return a fixed value to keep simulation deterministic even
- // along misspeculated paths.
- data = (T)-1;
-
- // Commit will have to clean up whatever happened. Set this
- // instruction as executed.
- this->setExecuted();
- }
-
- if (traceData) {
- traceData->setAddr(addr);
- traceData->setData(data);
- }
-
- return fault;
-}
-
-template<class Impl>
-template<class T>
-inline Fault
-BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
-{
- if (traceData) {
- traceData->setAddr(addr);
- traceData->setData(data);
- }
-
- req = new MemReq(addr, thread->getXCProxy(), sizeof(T), flags);
-
- req->asid = asid;
- req->thread_num = threadNumber;
- req->pc = this->PC;
-
- if ((req->vaddr & (TheISA::VMPageSize - 1)) + req->size >
- TheISA::VMPageSize) {
- return TheISA::genAlignmentFault();
- }
-
- fault = cpu->translateDataWriteReq(req);
-
- effAddr = req->vaddr;
- physEffAddr = req->paddr;
- memReqFlags = req->flags;
-
- if (fault == NoFault) {
-#if FULL_SYSTEM
- if (cpu->system->memctrl->badaddr(physEffAddr)) {
- fault = TheISA::genMachineCheckFault();
- } else {
- fault = cpu->write(req, data, sqIdx);
- }
-#else
- fault = cpu->write(req, data, sqIdx);
-#endif
- }
-
- if (res) {
- // always return some result to keep misspeculated paths
- // (which will ignore faults) deterministic
- *res = (fault == NoFault) ? req->result : 0;
- }
-
- return fault;
-}
-
-#endif // __CPU_BASE_DYN_INST_HH__
diff --git a/cpu/checker/cpu.cc b/cpu/checker/cpu.cc
deleted file mode 100644
index 41ff6e769..000000000
--- a/cpu/checker/cpu.cc
+++ /dev/null
@@ -1,757 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <list>
-#include <string>
-
-#include "base/refcnt.hh"
-#include "cpu/base.hh"
-#include "cpu/base_dyn_inst.hh"
-#include "cpu/checker/cpu.hh"
-#include "cpu/cpu_exec_context.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/static_inst.hh"
-#include "sim/byteswap.hh"
-#include "sim/sim_object.hh"
-#include "sim/stats.hh"
-
-#include "cpu/o3/alpha_dyn_inst.hh"
-#include "cpu/o3/alpha_impl.hh"
-
-#include "cpu/ozone/dyn_inst.hh"
-#include "cpu/ozone/ozone_impl.hh"
-#include "cpu/ozone/simple_impl.hh"
-
-#if FULL_SYSTEM
-#include "sim/system.hh"
-#include "arch/vtophys.hh"
-#endif // FULL_SYSTEM
-
-using namespace std;
-//The CheckerCPU does alpha only
-using namespace AlphaISA;
-
-void
-CheckerCPU::init()
-{
-}
-
-CheckerCPU::CheckerCPU(Params *p)
- : BaseCPU(p), cpuXC(NULL), xcProxy(NULL)
-{
- memReq = new MemReq();
- memReq->xc = xcProxy;
- memReq->asid = 0;
- memReq->data = new uint8_t[64];
-
- numInst = 0;
- startNumInst = 0;
- numLoad = 0;
- startNumLoad = 0;
- youngestSN = 0;
-
- changedPC = willChangePC = changedNextPC = false;
-
- exitOnError = p->exitOnError;
-#if FULL_SYSTEM
- itb = p->itb;
- dtb = p->dtb;
- systemPtr = NULL;
- memPtr = NULL;
-#endif
-}
-
-CheckerCPU::~CheckerCPU()
-{
-}
-
-void
-CheckerCPU::setMemory(FunctionalMemory *mem)
-{
- memPtr = mem;
-#if !FULL_SYSTEM
- cpuXC = new CPUExecContext(this, /* thread_num */ 0, mem,
- /* asid */ 0);
-
- cpuXC->setStatus(ExecContext::Suspended);
- xcProxy = cpuXC->getProxy();
- execContexts.push_back(xcProxy);
-#else
- if (systemPtr) {
- cpuXC = new CPUExecContext(this, 0, systemPtr, itb, dtb, memPtr, false);
-
- cpuXC->setStatus(ExecContext::Suspended);
- xcProxy = cpuXC->getProxy();
- execContexts.push_back(xcProxy);
- memReq->xc = xcProxy;
- delete cpuXC->kernelStats;
- cpuXC->kernelStats = NULL;
- }
-#endif
-}
-
-#if FULL_SYSTEM
-void
-CheckerCPU::setSystem(System *system)
-{
- systemPtr = system;
-
- if (memPtr) {
- cpuXC = new CPUExecContext(this, 0, systemPtr, itb, dtb, memPtr, false);
-
- cpuXC->setStatus(ExecContext::Suspended);
- xcProxy = cpuXC->getProxy();
- execContexts.push_back(xcProxy);
- memReq->xc = xcProxy;
- delete cpuXC->kernelStats;
- cpuXC->kernelStats = NULL;
- }
-}
-#endif
-
-void
-CheckerCPU::serialize(ostream &os)
-{
-/*
- BaseCPU::serialize(os);
- SERIALIZE_SCALAR(inst);
- nameOut(os, csprintf("%s.xc", name()));
- cpuXC->serialize(os);
- cacheCompletionEvent.serialize(os);
-*/
-}
-
-void
-CheckerCPU::unserialize(Checkpoint *cp, const string &section)
-{
-/*
- BaseCPU::unserialize(cp, section);
- UNSERIALIZE_SCALAR(inst);
- cpuXC->unserialize(cp, csprintf("%s.xc", section));
-*/
-}
-
-Fault
-CheckerCPU::copySrcTranslate(Addr src)
-{
- panic("Unimplemented!");
-}
-
-Fault
-CheckerCPU::copy(Addr dest)
-{
- panic("Unimplemented!");
-}
-
-template <class T>
-Fault
-CheckerCPU::read(Addr addr, T &data, unsigned flags)
-{
- memReq->reset(addr, sizeof(T), flags);
-
- // translate to physical address
- translateDataReadReq(memReq);
-
- memReq->cmd = Read;
- memReq->completionEvent = NULL;
- memReq->time = curTick;
- memReq->flags &= ~INST_READ;
-
- if (!(memReq->flags & UNCACHEABLE)) {
- // Access memory to see if we have the same data
- cpuXC->read(memReq, data);
- } else {
- // Assume the data is correct if it's an uncached access
- memcpy(&data, &unverifiedResult.integer, sizeof(T));
- }
-
- return NoFault;
-}
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-
-template
-Fault
-CheckerCPU::read(Addr addr, uint64_t &data, unsigned flags);
-
-template
-Fault
-CheckerCPU::read(Addr addr, uint32_t &data, unsigned flags);
-
-template
-Fault
-CheckerCPU::read(Addr addr, uint16_t &data, unsigned flags);
-
-template
-Fault
-CheckerCPU::read(Addr addr, uint8_t &data, unsigned flags);
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS
-
-template<>
-Fault
-CheckerCPU::read(Addr addr, double &data, unsigned flags)
-{
- return read(addr, *(uint64_t*)&data, flags);
-}
-
-template<>
-Fault
-CheckerCPU::read(Addr addr, float &data, unsigned flags)
-{
- return read(addr, *(uint32_t*)&data, flags);
-}
-
-template<>
-Fault
-CheckerCPU::read(Addr addr, int32_t &data, unsigned flags)
-{
- return read(addr, (uint32_t&)data, flags);
-}
-
-template <class T>
-Fault
-CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
-{
- memReq->reset(addr, sizeof(T), flags);
-
- // translate to physical address
- cpuXC->translateDataWriteReq(memReq);
-
- // Can compare the write data and result only if it's cacheable,
- // not a store conditional, or is a store conditional that
- // succeeded.
- // @todo: Verify that actual memory matches up with these values.
- // Right now it only verifies that the instruction data is the
- // same as what was in the request that got sent to memory; there
- // is no verification that it is the same as what is in memory.
- // This is because the LSQ would have to be snooped in the CPU to
- // verify this data.
- if (unverifiedReq &&
- !(unverifiedReq->flags & UNCACHEABLE) &&
- (!(unverifiedReq->flags & LOCKED) ||
- ((unverifiedReq->flags & LOCKED) &&
- unverifiedReq->result == 1))) {
-#if 0
- memReq->cmd = Read;
- memReq->completionEvent = NULL;
- memReq->time = curTick;
- memReq->flags &= ~INST_READ;
- cpuXC->read(memReq, inst_data);
-#endif
- T inst_data;
- memcpy(&inst_data, unverifiedReq->data, sizeof(T));
-
- if (data != inst_data) {
- warn("%lli: Store value does not match value in memory! "
- "Instruction: %#x, memory: %#x",
- curTick, inst_data, data);
- handleError();
- }
- }
-
- // Assume the result was the same as the one passed in. This checker
- // doesn't check if the SC should succeed or fail, it just checks the
- // value.
- if (res)
- *res = unverifiedReq->result;
-
- return NoFault;
-}
-
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-template
-Fault
-CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
-
-template
-Fault
-CheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
-
-template
-Fault
-CheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
-
-template
-Fault
-CheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS
-
-template<>
-Fault
-CheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
-{
- return write(*(uint64_t*)&data, addr, flags, res);
-}
-
-template<>
-Fault
-CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
-{
- return write(*(uint32_t*)&data, addr, flags, res);
-}
-
-template<>
-Fault
-CheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
-{
- return write((uint32_t)data, addr, flags, res);
-}
-
-
-#if FULL_SYSTEM
-Addr
-CheckerCPU::dbg_vtophys(Addr addr)
-{
- return vtophys(xcProxy, addr);
-}
-#endif // FULL_SYSTEM
-
-bool
-CheckerCPU::translateInstReq(MemReqPtr &req)
-{
-#if FULL_SYSTEM
- return (cpuXC->translateInstReq(req) == NoFault);
-#else
- cpuXC->translateInstReq(req);
- return true;
-#endif
-}
-
-void
-CheckerCPU::translateDataReadReq(MemReqPtr &req)
-{
- cpuXC->translateDataReadReq(req);
-
- if (req->vaddr != unverifiedReq->vaddr) {
- warn("%lli: Request virtual addresses do not match! Inst: %#x, "
- "checker: %#x",
- curTick, unverifiedReq->vaddr, req->vaddr);
- handleError();
- }
- req->paddr = unverifiedReq->paddr;
-
- if (checkFlags(req)) {
- warn("%lli: Request flags do not match! Inst: %#x, checker: %#x",
- curTick, unverifiedReq->flags, req->flags);
- handleError();
- }
-}
-
-void
-CheckerCPU::translateDataWriteReq(MemReqPtr &req)
-{
- cpuXC->translateDataWriteReq(req);
-
- if (req->vaddr != unverifiedReq->vaddr) {
- warn("%lli: Request virtual addresses do not match! Inst: %#x, "
- "checker: %#x",
- curTick, unverifiedReq->vaddr, req->vaddr);
- handleError();
- }
- req->paddr = unverifiedReq->paddr;
-
- if (checkFlags(req)) {
- warn("%lli: Request flags do not match! Inst: %#x, checker: %#x",
- curTick, unverifiedReq->flags, req->flags);
- handleError();
- }
-}
-
-bool
-CheckerCPU::checkFlags(MemReqPtr &req)
-{
- // Remove any dynamic flags that don't have to do with the request itself.
- unsigned flags = unverifiedReq->flags;
- unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT;
- flags = flags & (mask);
- if (flags == req->flags) {
- return false;
- } else {
- return true;
- }
-}
-
-template <class DynInstPtr>
-void
-Checker<DynInstPtr>::tick(DynInstPtr &completed_inst)
-{
- DynInstPtr inst;
-
- // Either check this instruction, or add it to a list of
- // instructions waiting to be checked. Instructions must be
- // checked in program order, so if a store has committed yet not
- // completed, there may be some instructions that are waiting
- // behind it that have completed and must be checked.
- if (!instList.empty()) {
- if (youngestSN < completed_inst->seqNum) {
- DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
- completed_inst->seqNum, completed_inst->readPC());
- instList.push_back(completed_inst);
- youngestSN = completed_inst->seqNum;
- }
-
- if (!instList.front()->isCompleted()) {
- return;
- } else {
- inst = instList.front();
- instList.pop_front();
- }
- } else {
- if (!completed_inst->isCompleted()) {
- if (youngestSN < completed_inst->seqNum) {
- DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
- completed_inst->seqNum, completed_inst->readPC());
- instList.push_back(completed_inst);
- youngestSN = completed_inst->seqNum;
- }
- return;
- } else {
- if (youngestSN < completed_inst->seqNum) {
- inst = completed_inst;
- youngestSN = completed_inst->seqNum;
- } else {
- return;
- }
- }
- }
-
- // Try to check all instructions that are completed, ending if we
- // run out of instructions to check or if an instruction is not
- // yet completed.
- while (1) {
- DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n",
- inst->seqNum, inst->readPC());
- unverifiedResult.integer = inst->readIntResult();
- unverifiedReq = inst->req;
- numCycles++;
-
- Fault fault = NoFault;
-
- // maintain $r0 semantics
- cpuXC->setIntReg(ZeroReg, 0);
-#ifdef TARGET_ALPHA
- cpuXC->setFloatRegDouble(ZeroReg, 0.0);
-#endif // TARGET_ALPHA
-
- // Check if any recent PC changes match up with anything we
- // expect to happen. This is mostly to check if traps or
- // PC-based events have occurred in both the checker and CPU.
- if (changedPC) {
- DPRINTF(Checker, "Changed PC recently to %#x\n",
- cpuXC->readPC());
- if (willChangePC) {
- if (newPC == cpuXC->readPC()) {
- DPRINTF(Checker, "Changed PC matches expected PC\n");
- } else {
- warn("%lli: Changed PC does not match expected PC, "
- "changed: %#x, expected: %#x",
- curTick, cpuXC->readPC(), newPC);
- handleError();
- }
- willChangePC = false;
- }
- changedPC = false;
- }
- if (changedNextPC) {
- DPRINTF(Checker, "Changed NextPC recently to %#x\n",
- cpuXC->readNextPC());
- changedNextPC = false;
- }
-
- // Try to fetch the instruction
-
-#if FULL_SYSTEM
-#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0
-#else
-#define IFETCH_FLAGS(pc) 0
-#endif
-
- // set up memory request for instruction fetch
- memReq->cmd = Read;
- memReq->reset(cpuXC->readPC() & ~3, sizeof(uint32_t),
- IFETCH_FLAGS(cpuXC->readPC()));
-
- bool succeeded = translateInstReq(memReq);
-
- if (!succeeded) {
- if (inst->getFault() == NoFault) {
- // In this case the instruction was not a dummy
- // instruction carrying an ITB fault. In the single
- // threaded case the ITB should still be able to
- // translate this instruction; in the SMT case it's
- // possible that its ITB entry was kicked out.
- warn("%lli: Instruction PC %#x was not found in the ITB!",
- curTick, cpuXC->readPC());
- handleError();
-
- // go to the next instruction
- cpuXC->setPC(cpuXC->readNextPC());
- cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst));
-
- return;
- } else {
- // The instruction is carrying an ITB fault. Handle
- // the fault and see if our results match the CPU on
- // the next tick().
- fault = inst->getFault();
- }
- }
-
- if (fault == NoFault) {
- cpuXC->mem->read(memReq, machInst);
-
- // keep an instruction count
- numInst++;
-
- // decode the instruction
- machInst = gtoh(machInst);
- // Checks that the instruction matches what we expected it to be.
- // Checks both the machine instruction and the PC.
- validateInst(inst);
-
- curStaticInst = StaticInst::decode(makeExtMI(machInst,
- cpuXC->readPC()));
-
-#if FULL_SYSTEM
- cpuXC->setInst(machInst);
-#endif // FULL_SYSTEM
-
- fault = inst->getFault();
- }
-
- // Either the instruction was a fault and we should process the fault,
- // or we should just go ahead execute the instruction. This assumes
- // that the instruction is properly marked as a fault.
- if (fault == NoFault) {
-
- cpuXC->func_exe_inst++;
-
- fault = curStaticInst->execute(this, NULL);
-
- // Checks to make sure instrution results are correct.
- validateExecution(inst);
-
- if (curStaticInst->isLoad()) {
- ++numLoad;
- }
- }
-
- if (fault != NoFault) {
-#if FULL_SYSTEM
- fault->invoke(xcProxy);
- willChangePC = true;
- newPC = cpuXC->readPC();
- DPRINTF(Checker, "Fault, PC is now %#x\n", newPC);
-#else // !FULL_SYSTEM
- fatal("fault (%d) detected @ PC 0x%08p", fault, cpuXC->readPC());
-#endif // FULL_SYSTEM
- } else {
-#if THE_ISA != MIPS_ISA
- // go to the next instruction
- cpuXC->setPC(cpuXC->readNextPC());
- cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst));
-#else
- // go to the next instruction
- cpuXC->setPC(cpuXC->readNextPC());
- cpuXC->setNextPC(cpuXC->readNextNPC());
- cpuXC->setNextNPC(cpuXC->readNextNPC() + sizeof(MachInst));
-#endif
-
- }
-
-#if FULL_SYSTEM
- // @todo: Determine if these should happen only if the
- // instruction hasn't faulted. In the SimpleCPU case this may
- // not be true, but in the O3 or Ozone case this may be true.
- Addr oldpc;
- int count = 0;
- do {
- oldpc = cpuXC->readPC();
- system->pcEventQueue.service(xcProxy);
- count++;
- } while (oldpc != cpuXC->readPC());
- if (count > 1) {
- willChangePC = true;
- newPC = cpuXC->readPC();
- DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC);
- }
-#endif
-
- // @todo: Optionally can check all registers. (Or just those
- // that have been modified).
- validateState();
-
- // Continue verifying instructions if there's another completed
- // instruction waiting to be verified.
- if (instList.empty()) {
- break;
- } else if (instList.front()->isCompleted()) {
- inst = instList.front();
- instList.pop_front();
- } else {
- break;
- }
- }
-}
-
-template <class DynInstPtr>
-void
-Checker<DynInstPtr>::switchOut(Sampler *s)
-{
- instList.clear();
-}
-
-template <class DynInstPtr>
-void
-Checker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU)
-{
-}
-
-template <class DynInstPtr>
-void
-Checker<DynInstPtr>::validateInst(DynInstPtr &inst)
-{
- if (inst->readPC() != cpuXC->readPC()) {
- warn("%lli: PCs do not match! Inst: %#x, checker: %#x",
- curTick, inst->readPC(), cpuXC->readPC());
- if (changedPC) {
- warn("%lli: Changed PCs recently, may not be an error",
- curTick);
- } else {
- handleError();
- }
- }
-
- MachInst mi = static_cast<MachInst>(inst->staticInst->machInst);
-
- if (mi != machInst) {
- warn("%lli: Binary instructions do not match! Inst: %#x, "
- "checker: %#x",
- curTick, mi, machInst);
- handleError();
- }
-}
-
-template <class DynInstPtr>
-void
-Checker<DynInstPtr>::validateExecution(DynInstPtr &inst)
-{
- if (inst->numDestRegs()) {
- // @todo: Support more destination registers.
- if (inst->isUnverifiable()) {
- // Unverifiable instructions assume they were executed
- // properly by the CPU. Grab the result from the
- // instruction and write it to the register.
- RegIndex idx = inst->destRegIdx(0);
- if (idx < TheISA::FP_Base_DepTag) {
- cpuXC->setIntReg(idx, inst->readIntResult());
- } else if (idx < TheISA::Fpcr_DepTag) {
- cpuXC->setFloatRegInt(idx, inst->readIntResult());
- } else {
- cpuXC->setMiscReg(idx, inst->readIntResult());
- }
- } else if (result.integer != inst->readIntResult()) {
- warn("%lli: Instruction results do not match! (Results may not "
- "actually be integers) Inst: %#x, checker: %#x",
- curTick, inst->readIntResult(), result.integer);
- handleError();
- }
- }
-
- if (inst->readNextPC() != cpuXC->readNextPC()) {
- warn("%lli: Instruction next PCs do not match! Inst: %#x, "
- "checker: %#x",
- curTick, inst->readNextPC(), cpuXC->readNextPC());
- handleError();
- }
-
- // Checking side effect registers can be difficult if they are not
- // checked simultaneously with the execution of the instruction.
- // This is because other valid instructions may have modified
- // these registers in the meantime, and their values are not
- // stored within the DynInst.
- while (!miscRegIdxs.empty()) {
- int misc_reg_idx = miscRegIdxs.front();
- miscRegIdxs.pop();
-
- if (inst->xcBase()->readMiscReg(misc_reg_idx) !=
- cpuXC->readMiscReg(misc_reg_idx)) {
- warn("%lli: Misc reg idx %i (side effect) does not match! "
- "Inst: %#x, checker: %#x",
- curTick, misc_reg_idx,
- inst->xcBase()->readMiscReg(misc_reg_idx),
- cpuXC->readMiscReg(misc_reg_idx));
- handleError();
- }
- }
-}
-
-template <class DynInstPtr>
-void
-Checker<DynInstPtr>::validateState()
-{
-}
-
-template <class DynInstPtr>
-void
-Checker<DynInstPtr>::dumpInsts()
-{
- int num = 0;
-
- InstListIt inst_list_it = --(instList.end());
-
- cprintf("Inst list size: %i\n", instList.size());
-
- while (inst_list_it != instList.end())
- {
- cprintf("Instruction:%i\n",
- num);
-
- cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
- "Completed:%i\n",
- (*inst_list_it)->readPC(),
- (*inst_list_it)->seqNum,
- (*inst_list_it)->threadNumber,
- (*inst_list_it)->isCompleted());
-
- cprintf("\n");
-
- inst_list_it--;
- ++num;
- }
-
-}
-
-template
-class Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >;
-
-template
-class Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >;
diff --git a/cpu/checker/cpu.hh b/cpu/checker/cpu.hh
deleted file mode 100644
index 9fcd1037f..000000000
--- a/cpu/checker/cpu.hh
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_CHECKER_CPU_HH__
-#define __CPU_CHECKER_CPU_HH__
-
-#include <list>
-#include <queue>
-#include <map>
-
-#include "base/statistics.hh"
-#include "config/full_system.hh"
-#include "cpu/base.hh"
-#include "cpu/base_dyn_inst.hh"
-#include "cpu/cpu_exec_context.hh"
-#include "cpu/pc_event.hh"
-#include "cpu/static_inst.hh"
-#include "sim/eventq.hh"
-
-// forward declarations
-#if FULL_SYSTEM
-class Processor;
-class AlphaITB;
-class AlphaDTB;
-class PhysicalMemory;
-
-class RemoteGDB;
-class GDBListener;
-
-#else
-
-class Process;
-
-#endif // FULL_SYSTEM
-template <class>
-class BaseDynInst;
-class ExecContext;
-class MemInterface;
-class Checkpoint;
-class Sampler;
-
-/**
- * CheckerCPU class. Dynamically verifies instructions as they are
- * completed by making sure that the instruction and its results match
- * the independent execution of the benchmark inside the checker. The
- * checker verifies instructions in order, regardless of the order in
- * which instructions complete. There are certain results that can
- * not be verified, specifically the result of a store conditional or
- * the values of uncached accesses. In these cases, and with
- * instructions marked as "IsUnverifiable", the checker assumes that
- * the value from the main CPU's execution is correct and simply
- * copies that value. It provides a CheckerExecContext (see
- * checker/exec_context.hh) that provides hooks for updating the
- * Checker's state through any ExecContext accesses. This allows the
- * checker to be able to correctly verify instructions, even with
- * external accesses to the ExecContext that change state.
- */
-class CheckerCPU : public BaseCPU
-{
- protected:
- typedef TheISA::MachInst MachInst;
- typedef TheISA::MiscReg MiscReg;
- public:
- virtual void init();
-
- struct Params : public BaseCPU::Params
- {
-#if FULL_SYSTEM
- AlphaITB *itb;
- AlphaDTB *dtb;
- FunctionalMemory *mem;
-#else
- Process *process;
-#endif
- bool exitOnError;
- };
-
- public:
- CheckerCPU(Params *p);
- virtual ~CheckerCPU();
-
- void setMemory(FunctionalMemory *mem);
-
- FunctionalMemory *memPtr;
-
-#if FULL_SYSTEM
- void setSystem(System *system);
-
- System *systemPtr;
-#endif
- public:
- // execution context
- CPUExecContext *cpuXC;
-
- ExecContext *xcProxy;
-
- AlphaITB *itb;
- AlphaDTB *dtb;
-
-#if FULL_SYSTEM
- Addr dbg_vtophys(Addr addr);
-#endif
-
- union Result {
- uint64_t integer;
- float fp;
- double dbl;
- };
-
- Result result;
-
- // current instruction
- MachInst machInst;
-
- // Refcounted pointer to the one memory request.
- MemReqPtr memReq;
-
- StaticInstPtr curStaticInst;
-
- // number of simulated instructions
- Counter numInst;
- Counter startNumInst;
-
- std::queue<int> miscRegIdxs;
-
- virtual Counter totalInstructions() const
- {
- return numInst - startNumInst;
- }
-
- // number of simulated loads
- Counter numLoad;
- Counter startNumLoad;
-
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-
- template <class T>
- Fault read(Addr addr, T &data, unsigned flags);
-
- template <class T>
- Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
-
- // These functions are only used in CPU models that split
- // effective address computation from the actual memory access.
- void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
- Addr getEA() { panic("SimpleCPU::getEA() not implemented\n"); }
-
- void prefetch(Addr addr, unsigned flags)
- {
- // need to do this...
- }
-
- void writeHint(Addr addr, int size, unsigned flags)
- {
- // need to do this...
- }
-
- Fault copySrcTranslate(Addr src);
-
- Fault copy(Addr dest);
-
- // The register accessor methods provide the index of the
- // instruction's operand (e.g., 0 or 1), not the architectural
- // register index, to simplify the implementation of register
- // renaming. We find the architectural register index by indexing
- // into the instruction's own operand index table. Note that a
- // raw pointer to the StaticInst is provided instead of a
- // ref-counted StaticInstPtr to redice overhead. This is fine as
- // long as these methods don't copy the pointer into any long-term
- // storage (which is pretty hard to imagine they would have reason
- // to do).
-
- uint64_t readIntReg(const StaticInst *si, int idx)
- {
- return cpuXC->readIntReg(si->srcRegIdx(idx));
- }
-
- float readFloatRegSingle(const StaticInst *si, int idx)
- {
- int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return cpuXC->readFloatRegSingle(reg_idx);
- }
-
- double readFloatRegDouble(const StaticInst *si, int idx)
- {
- int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return cpuXC->readFloatRegDouble(reg_idx);
- }
-
- uint64_t readFloatRegInt(const StaticInst *si, int idx)
- {
- int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return cpuXC->readFloatRegInt(reg_idx);
- }
-
- void setIntReg(const StaticInst *si, int idx, uint64_t val)
- {
- cpuXC->setIntReg(si->destRegIdx(idx), val);
- result.integer = val;
- }
-
- void setFloatRegSingle(const StaticInst *si, int idx, float val)
- {
- int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- cpuXC->setFloatRegSingle(reg_idx, val);
- result.fp = val;
- }
-
- void setFloatRegDouble(const StaticInst *si, int idx, double val)
- {
- int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- cpuXC->setFloatRegDouble(reg_idx, val);
- result.dbl = val;
- }
-
- void setFloatRegInt(const StaticInst *si, int idx, uint64_t val)
- {
- int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- cpuXC->setFloatRegInt(reg_idx, val);
- result.integer = val;
- }
-
- uint64_t readPC() { return cpuXC->readPC(); }
- void setNextPC(uint64_t val) {
- cpuXC->setNextPC(val);
- }
-
- MiscReg readMiscReg(int misc_reg)
- {
- return cpuXC->readMiscReg(misc_reg);
- }
-
- MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
- {
- return cpuXC->readMiscRegWithEffect(misc_reg, fault);
- }
-
- Fault setMiscReg(int misc_reg, const MiscReg &val)
- {
- result.integer = val;
- miscRegIdxs.push(misc_reg);
- return cpuXC->setMiscReg(misc_reg, val);
- }
-
- Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
- {
- miscRegIdxs.push(misc_reg);
- return cpuXC->setMiscRegWithEffect(misc_reg, val);
- }
-
- void recordPCChange(uint64_t val) { changedPC = true; }
- void recordNextPCChange(uint64_t val) { changedNextPC = true; }
-
- bool translateInstReq(MemReqPtr &req);
- void translateDataWriteReq(MemReqPtr &req);
- void translateDataReadReq(MemReqPtr &req);
-
-#if FULL_SYSTEM
- Fault hwrei() { return cpuXC->hwrei(); }
- int readIntrFlag() { return cpuXC->readIntrFlag(); }
- void setIntrFlag(int val) { cpuXC->setIntrFlag(val); }
- bool inPalMode() { return cpuXC->inPalMode(); }
- void ev5_trap(Fault fault) { fault->invoke(xcProxy); }
- bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); }
-#else
- // Assume that the normal CPU's call to syscall was successful.
- // The checker's state would have already been updated by the syscall.
- void syscall() { }
-#endif
-
- void handleError()
- {
- if (exitOnError)
- panic("Checker found error!");
- }
- bool checkFlags(MemReqPtr &req);
-
- ExecContext *xcBase() { return xcProxy; }
- CPUExecContext *cpuXCBase() { return cpuXC; }
-
- Result unverifiedResult;
- MemReqPtr unverifiedReq;
-
- bool changedPC;
- bool willChangePC;
- uint64_t newPC;
- bool changedNextPC;
- bool exitOnError;
-
- InstSeqNum youngestSN;
-};
-
-/**
- * Templated Checker class. This Checker class is templated on the
- * DynInstPtr of the instruction type that will be verified. Proper
- * template instantiations of the Checker must be placed at the bottom
- * of checker/cpu.cc.
- */
-template <class DynInstPtr>
-class Checker : public CheckerCPU
-{
- public:
- Checker(Params *p)
- : CheckerCPU(p)
- { }
-
- void switchOut(Sampler *s);
- void takeOverFrom(BaseCPU *oldCPU);
-
- void tick(DynInstPtr &inst);
-
- void validateInst(DynInstPtr &inst);
- void validateExecution(DynInstPtr &inst);
- void validateState();
-
- std::list<DynInstPtr> instList;
- typedef typename std::list<DynInstPtr>::iterator InstListIt;
- void dumpInsts();
-};
-
-#endif // __CPU_CHECKER_CPU_HH__
diff --git a/cpu/checker/cpu_builder.cc b/cpu/checker/cpu_builder.cc
deleted file mode 100644
index d80daef97..000000000
--- a/cpu/checker/cpu_builder.cc
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <string>
-
-#include "cpu/checker/cpu.hh"
-#include "cpu/inst_seq.hh"
-#include "cpu/ozone/dyn_inst.hh"
-#include "cpu/ozone/ozone_impl.hh"
-#include "mem/base_mem.hh"
-#include "sim/builder.hh"
-#include "sim/process.hh"
-#include "sim/sim_object.hh"
-
-/**
- * Specific non-templated derived class used for SimObject configuration.
- */
-class OzoneChecker : public Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >
-{
- public:
- OzoneChecker(Params *p)
- : Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >(p)
- { }
-};
-
-////////////////////////////////////////////////////////////////////////
-//
-// CheckerCPU Simulation Object
-//
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(OzoneChecker)
-
- Param<Counter> max_insts_any_thread;
- Param<Counter> max_insts_all_threads;
- Param<Counter> max_loads_any_thread;
- Param<Counter> max_loads_all_threads;
-
-#if FULL_SYSTEM
- SimObjectParam<AlphaITB *> itb;
- SimObjectParam<AlphaDTB *> dtb;
- SimObjectParam<FunctionalMemory *> mem;
- SimObjectParam<System *> system;
- Param<int> cpu_id;
- Param<Tick> profile;
-#else
- SimObjectParam<Process *> workload;
-#endif // FULL_SYSTEM
- Param<int> clock;
- SimObjectParam<BaseMem *> icache;
- SimObjectParam<BaseMem *> dcache;
-
- Param<bool> defer_registration;
- Param<bool> exitOnError;
- Param<bool> function_trace;
- Param<Tick> function_trace_start;
-
-END_DECLARE_SIM_OBJECT_PARAMS(OzoneChecker)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(OzoneChecker)
-
- INIT_PARAM(max_insts_any_thread,
- "terminate when any thread reaches this inst count"),
- INIT_PARAM(max_insts_all_threads,
- "terminate when all threads have reached this inst count"),
- INIT_PARAM(max_loads_any_thread,
- "terminate when any thread reaches this load count"),
- INIT_PARAM(max_loads_all_threads,
- "terminate when all threads have reached this load count"),
-
-#if FULL_SYSTEM
- INIT_PARAM(itb, "Instruction TLB"),
- INIT_PARAM(dtb, "Data TLB"),
- INIT_PARAM(mem, "memory"),
- INIT_PARAM(system, "system object"),
- INIT_PARAM(cpu_id, "processor ID"),
- INIT_PARAM(profile, ""),
-#else
- INIT_PARAM(workload, "processes to run"),
-#endif // FULL_SYSTEM
-
- INIT_PARAM(clock, "clock speed"),
- INIT_PARAM(icache, "L1 instruction cache object"),
- INIT_PARAM(dcache, "L1 data cache object"),
-
- INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
- INIT_PARAM(exitOnError, "exit on error"),
- INIT_PARAM(function_trace, "Enable function trace"),
- INIT_PARAM(function_trace_start, "Cycle to start function trace")
-
-END_INIT_SIM_OBJECT_PARAMS(OzoneChecker)
-
-
-CREATE_SIM_OBJECT(OzoneChecker)
-{
- OzoneChecker::Params *params = new OzoneChecker::Params();
- params->name = getInstanceName();
- params->numberOfThreads = 1;
- params->max_insts_any_thread = 0;
- params->max_insts_all_threads = 0;
- params->max_loads_any_thread = 0;
- params->max_loads_all_threads = 0;
- params->exitOnError = exitOnError;
- params->deferRegistration = defer_registration;
- params->functionTrace = function_trace;
- params->functionTraceStart = function_trace_start;
- params->clock = clock;
- // Hack to touch all parameters. Consider not deriving Checker
- // from BaseCPU..it's not really a CPU in the end.
- Counter temp;
- temp = max_insts_any_thread;
- temp = max_insts_all_threads;
- temp = max_loads_any_thread;
- temp = max_loads_all_threads;
- BaseMem *cache = icache;
- cache = dcache;
-
-#if FULL_SYSTEM
- params->itb = itb;
- params->dtb = dtb;
- params->mem = mem;
- params->system = system;
- params->cpu_id = cpu_id;
- params->profile = profile;
-#else
- params->process = workload;
-#endif
-
- OzoneChecker *cpu = new OzoneChecker(params);
- return cpu;
-}
-
-REGISTER_SIM_OBJECT("OzoneChecker", OzoneChecker)
diff --git a/cpu/checker/exec_context.hh b/cpu/checker/exec_context.hh
deleted file mode 100644
index 9f9fb0fd6..000000000
--- a/cpu/checker/exec_context.hh
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_CHECKER_EXEC_CONTEXT_HH__
-#define __CPU_CHECKER_EXEC_CONTEXT_HH__
-
-#include "cpu/checker/cpu.hh"
-#include "cpu/cpu_exec_context.hh"
-#include "cpu/exec_context.hh"
-
-class EndQuiesceEvent;
-namespace Kernel {
- class Statistics;
-};
-
-/**
- * Derived ExecContext class for use with the Checker. The template
- * parameter is the ExecContext class used by the specific CPU being
- * verified. This CheckerExecContext is then used by the main CPU in
- * place of its usual ExecContext class. It handles updating the
- * checker's state any time state is updated through the ExecContext.
- */
-template <class XC>
-class CheckerExecContext : public ExecContext
-{
- public:
- CheckerExecContext(XC *actual_xc,
- CheckerCPU *checker_cpu)
- : actualXC(actual_xc), checkerXC(checker_cpu->cpuXC),
- checkerCPU(checker_cpu)
- { }
-
- private:
- XC *actualXC;
- CPUExecContext *checkerXC;
- CheckerCPU *checkerCPU;
-
- public:
-
- BaseCPU *getCpuPtr() { return actualXC->getCpuPtr(); }
-
- void setCpuId(int id)
- {
- actualXC->setCpuId(id);
- checkerXC->setCpuId(id);
- }
-
- int readCpuId() { return actualXC->readCpuId(); }
-
- FunctionalMemory *getMemPtr() { return actualXC->getMemPtr(); }
-
-#if FULL_SYSTEM
- System *getSystemPtr() { return actualXC->getSystemPtr(); }
-
- PhysicalMemory *getPhysMemPtr() { return actualXC->getPhysMemPtr(); }
-
- AlphaITB *getITBPtr() { return actualXC->getITBPtr(); }
-
- AlphaDTB *getDTBPtr() { return actualXC->getDTBPtr(); }
-
- Kernel::Statistics *getKernelStats() { return actualXC->getKernelStats(); }
-#else
- Process *getProcessPtr() { return actualXC->getProcessPtr(); }
-#endif
-
- Status status() const { return actualXC->status(); }
-
- void setStatus(Status new_status)
- {
- actualXC->setStatus(new_status);
- checkerXC->setStatus(new_status);
- }
-
- /// Set the status to Active. Optional delay indicates number of
- /// cycles to wait before beginning execution.
- void activate(int delay = 1) { actualXC->activate(delay); }
-
- /// Set the status to Suspended.
- void suspend() { actualXC->suspend(); }
-
- /// Set the status to Unallocated.
- void deallocate() { actualXC->deallocate(); }
-
- /// Set the status to Halted.
- void halt() { actualXC->halt(); }
-
-#if FULL_SYSTEM
- void dumpFuncProfile() { actualXC->dumpFuncProfile(); }
-#endif
-
- void takeOverFrom(ExecContext *oldContext)
- {
- actualXC->takeOverFrom(oldContext);
- checkerXC->takeOverFrom(oldContext);
- }
-
- void regStats(const std::string &name) { actualXC->regStats(name); }
-
- void serialize(std::ostream &os) { actualXC->serialize(os); }
- void unserialize(Checkpoint *cp, const std::string &section)
- { actualXC->unserialize(cp, section); }
-
-#if FULL_SYSTEM
- EndQuiesceEvent *getQuiesceEvent() { return actualXC->getQuiesceEvent(); }
-
- Tick readLastActivate() { return actualXC->readLastActivate(); }
- Tick readLastSuspend() { return actualXC->readLastSuspend(); }
-
- void profileClear() { return actualXC->profileClear(); }
- void profileSample() { return actualXC->profileSample(); }
-#endif
-
- int getThreadNum() { return actualXC->getThreadNum(); }
-
- // @todo: Do I need this?
- MachInst getInst() { return actualXC->getInst(); }
-
- // @todo: Do I need this?
- void copyArchRegs(ExecContext *xc)
- {
- actualXC->copyArchRegs(xc);
- checkerXC->copyArchRegs(xc);
- }
-
- void clearArchRegs()
- {
- actualXC->clearArchRegs();
- checkerXC->clearArchRegs();
- }
-
- //
- // New accessors for new decoder.
- //
- uint64_t readIntReg(int reg_idx)
- { return actualXC->readIntReg(reg_idx); }
-
- float readFloatRegSingle(int reg_idx)
- { return actualXC->readFloatRegSingle(reg_idx); }
-
- double readFloatRegDouble(int reg_idx)
- { return actualXC->readFloatRegDouble(reg_idx); }
-
- uint64_t readFloatRegInt(int reg_idx)
- { return actualXC->readFloatRegInt(reg_idx); }
-
- void setIntReg(int reg_idx, uint64_t val)
- {
- actualXC->setIntReg(reg_idx, val);
- checkerXC->setIntReg(reg_idx, val);
- }
-
- void setFloatRegSingle(int reg_idx, float val)
- {
- actualXC->setFloatRegSingle(reg_idx, val);
- checkerXC->setFloatRegSingle(reg_idx, val);
- }
-
- void setFloatRegDouble(int reg_idx, double val)
- {
- actualXC->setFloatRegDouble(reg_idx, val);
- checkerXC->setFloatRegSingle(reg_idx, val);
- }
-
- void setFloatRegInt(int reg_idx, uint64_t val)
- {
- actualXC->setFloatRegInt(reg_idx, val);
- checkerXC->setFloatRegInt(reg_idx, val);
- }
-
- uint64_t readPC() { return actualXC->readPC(); }
-
- void setPC(uint64_t val)
- {
- actualXC->setPC(val);
- checkerXC->setPC(val);
- checkerCPU->recordPCChange(val);
- }
-
- uint64_t readNextPC() { return actualXC->readNextPC(); }
-
- void setNextPC(uint64_t val)
- {
- actualXC->setNextPC(val);
- checkerXC->setNextPC(val);
- checkerCPU->recordNextPCChange(val);
- }
-
- MiscReg readMiscReg(int misc_reg)
- { return actualXC->readMiscReg(misc_reg); }
-
- MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
- { return actualXC->readMiscRegWithEffect(misc_reg, fault); }
-
- Fault setMiscReg(int misc_reg, const MiscReg &val)
- {
- checkerXC->setMiscReg(misc_reg, val);
- return actualXC->setMiscReg(misc_reg, val);
- }
-
- Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
- {
- checkerXC->setMiscRegWithEffect(misc_reg, val);
- return actualXC->setMiscRegWithEffect(misc_reg, val);
- }
-
- unsigned readStCondFailures()
- { return actualXC->readStCondFailures(); }
-
- void setStCondFailures(unsigned sc_failures)
- {
- checkerXC->setStCondFailures(sc_failures);
- actualXC->setStCondFailures(sc_failures);
- }
-#if FULL_SYSTEM
- bool inPalMode() { return actualXC->inPalMode(); }
-#endif
-
- // @todo: Fix this!
- bool misspeculating() { return actualXC->misspeculating(); }
-
-#if !FULL_SYSTEM
- IntReg getSyscallArg(int i) { return actualXC->getSyscallArg(i); }
-
- // used to shift args for indirect syscall
- void setSyscallArg(int i, IntReg val)
- {
- checkerXC->setSyscallArg(i, val);
- actualXC->setSyscallArg(i, val);
- }
-
- void setSyscallReturn(SyscallReturn return_value)
- {
- checkerXC->setSyscallReturn(return_value);
- actualXC->setSyscallReturn(return_value);
- }
-
- Counter readFuncExeInst() { return actualXC->readFuncExeInst(); }
-#endif
-};
-
-#endif // __CPU_CHECKER_EXEC_CONTEXT_HH__
diff --git a/cpu/checker/o3_cpu_builder.cc b/cpu/checker/o3_cpu_builder.cc
deleted file mode 100644
index 410f91352..000000000
--- a/cpu/checker/o3_cpu_builder.cc
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <string>
-
-#include "cpu/checker/cpu.hh"
-#include "cpu/inst_seq.hh"
-#include "cpu/o3/alpha_dyn_inst.hh"
-#include "cpu/o3/alpha_impl.hh"
-#include "mem/base_mem.hh"
-#include "sim/builder.hh"
-#include "sim/process.hh"
-#include "sim/sim_object.hh"
-
-/**
- * Specific non-templated derived class used for SimObject configuration.
- */
-class O3Checker : public Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >
-{
- public:
- O3Checker(Params *p)
- : Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >(p)
- { }
-};
-
-////////////////////////////////////////////////////////////////////////
-//
-// CheckerCPU Simulation Object
-//
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(O3Checker)
-
- Param<Counter> max_insts_any_thread;
- Param<Counter> max_insts_all_threads;
- Param<Counter> max_loads_any_thread;
- Param<Counter> max_loads_all_threads;
-
-#if FULL_SYSTEM
- SimObjectParam<AlphaITB *> itb;
- SimObjectParam<AlphaDTB *> dtb;
- SimObjectParam<FunctionalMemory *> mem;
- SimObjectParam<System *> system;
- Param<int> cpu_id;
- Param<Tick> profile;
-#else
- SimObjectParam<Process *> workload;
-#endif // FULL_SYSTEM
- Param<int> clock;
- SimObjectParam<BaseMem *> icache;
- SimObjectParam<BaseMem *> dcache;
-
- Param<bool> defer_registration;
- Param<bool> exitOnError;
- Param<bool> function_trace;
- Param<Tick> function_trace_start;
-
-END_DECLARE_SIM_OBJECT_PARAMS(O3Checker)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(O3Checker)
-
- INIT_PARAM(max_insts_any_thread,
- "terminate when any thread reaches this inst count"),
- INIT_PARAM(max_insts_all_threads,
- "terminate when all threads have reached this inst count"),
- INIT_PARAM(max_loads_any_thread,
- "terminate when any thread reaches this load count"),
- INIT_PARAM(max_loads_all_threads,
- "terminate when all threads have reached this load count"),
-
-#if FULL_SYSTEM
- INIT_PARAM(itb, "Instruction TLB"),
- INIT_PARAM(dtb, "Data TLB"),
- INIT_PARAM(mem, "memory"),
- INIT_PARAM(system, "system object"),
- INIT_PARAM(cpu_id, "processor ID"),
- INIT_PARAM(profile, ""),
-#else
- INIT_PARAM(workload, "processes to run"),
-#endif // FULL_SYSTEM
-
- INIT_PARAM(clock, "clock speed"),
- INIT_PARAM(icache, "L1 instruction cache object"),
- INIT_PARAM(dcache, "L1 data cache object"),
-
- INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
- INIT_PARAM(exitOnError, "exit on error"),
- INIT_PARAM(function_trace, "Enable function trace"),
- INIT_PARAM(function_trace_start, "Cycle to start function trace")
-
-END_INIT_SIM_OBJECT_PARAMS(O3Checker)
-
-
-CREATE_SIM_OBJECT(O3Checker)
-{
- O3Checker::Params *params = new O3Checker::Params();
- params->name = getInstanceName();
- params->numberOfThreads = 1;
- params->max_insts_any_thread = 0;
- params->max_insts_all_threads = 0;
- params->max_loads_any_thread = 0;
- params->max_loads_all_threads = 0;
- params->exitOnError = exitOnError;
- params->deferRegistration = defer_registration;
- params->functionTrace = function_trace;
- params->functionTraceStart = function_trace_start;
- params->clock = clock;
- // Hack to touch all parameters. Consider not deriving Checker
- // from BaseCPU..it's not really a CPU in the end.
- Counter temp;
- temp = max_insts_any_thread;
- temp = max_insts_all_threads;
- temp = max_loads_any_thread;
- temp = max_loads_all_threads;
- BaseMem *cache = icache;
- cache = dcache;
-
-#if FULL_SYSTEM
- params->itb = itb;
- params->dtb = dtb;
- params->mem = mem;
- params->system = system;
- params->cpu_id = cpu_id;
- params->profile = profile;
-#else
- params->process = workload;
-#endif
-
- O3Checker *cpu = new O3Checker(params);
- return cpu;
-}
-
-REGISTER_SIM_OBJECT("O3Checker", O3Checker)
diff --git a/cpu/cpu_exec_context.cc b/cpu/cpu_exec_context.cc
deleted file mode 100644
index e30295ef8..000000000
--- a/cpu/cpu_exec_context.cc
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (c) 2001-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <string>
-
-#include "cpu/base.hh"
-#include "cpu/cpu_exec_context.hh"
-#include "cpu/exec_context.hh"
-
-#if FULL_SYSTEM
-#include "base/callback.hh"
-#include "base/cprintf.hh"
-#include "base/output.hh"
-#include "base/trace.hh"
-#include "cpu/profile.hh"
-#include "cpu/quiesce_event.hh"
-#include "kern/kernel_stats.hh"
-#include "sim/serialize.hh"
-#include "sim/sim_exit.hh"
-#include "sim/system.hh"
-#include "arch/stacktrace.hh"
-#else
-#include "sim/process.hh"
-#endif
-
-using namespace std;
-
-// constructor
-#if FULL_SYSTEM
-CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
- AlphaITB *_itb, AlphaDTB *_dtb,
- FunctionalMemory *_mem,
- bool use_kernel_stats)
- : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num),
- cpu_id(-1), lastActivate(0), lastSuspend(0), mem(_mem), itb(_itb),
- dtb(_dtb), system(_sys), memctrl(_sys->memctrl), physmem(_sys->physmem),
- profile(NULL), func_exe_inst(0), storeCondFailures(0)
-{
- proxy = new ProxyExecContext<CPUExecContext>(this);
-
- quiesceEvent = new EndQuiesceEvent(proxy);
-
- memset(&regs, 0, sizeof(RegFile));
-
- if (cpu->params->profile) {
- profile = new FunctionProfile(system->kernelSymtab);
- Callback *cb =
- new MakeCallback<CPUExecContext,
- &CPUExecContext::dumpFuncProfile>(this);
- registerExitCallback(cb);
- }
-
- // let's fill with a dummy node for now so we don't get a segfault
- // on the first cycle when there's no node available.
- static ProfileNode dummyNode;
- profileNode = &dummyNode;
- profilePC = 3;
-
- if (use_kernel_stats) {
- kernelStats = new Kernel::Statistics(system);
- } else {
- kernelStats = NULL;
- }
-}
-#else
-CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num,
- Process *_process, int _asid)
- : _status(ExecContext::Unallocated),
- cpu(_cpu), thread_num(_thread_num), cpu_id(-1), lastActivate(0),
- lastSuspend(0), process(_process), mem(process->getMemory()), asid(_asid),
- func_exe_inst(0), storeCondFailures(0)
-{
- memset(&regs, 0, sizeof(RegFile));
- proxy = new ProxyExecContext<CPUExecContext>(this);
-}
-
-CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num,
- FunctionalMemory *_mem, int _asid)
- : cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid),
- func_exe_inst(0), storeCondFailures(0)
-{
- memset(&regs, 0, sizeof(RegFile));
- proxy = new ProxyExecContext<CPUExecContext>(this);
-}
-
-CPUExecContext::CPUExecContext(RegFile *regFile)
- : cpu(NULL), thread_num(-1), process(NULL), mem(NULL), asid(-1),
- func_exe_inst(0), storeCondFailures(0)
-{
- regs = *regFile;
- proxy = new ProxyExecContext<CPUExecContext>(this);
-}
-
-#endif
-
-CPUExecContext::~CPUExecContext()
-{
- delete proxy;
-}
-
-#if FULL_SYSTEM
-void
-CPUExecContext::dumpFuncProfile()
-{
- std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name()));
- profile->dump(proxy, *os);
-}
-
-void
-CPUExecContext::profileClear()
-{
- if (profile)
- profile->clear();
-}
-
-void
-CPUExecContext::profileSample()
-{
- if (profile)
- profile->sample(profileNode, profilePC);
-}
-
-#endif
-
-void
-CPUExecContext::takeOverFrom(ExecContext *oldContext)
-{
- // some things should already be set up
- assert(mem == oldContext->getMemPtr());
-#if FULL_SYSTEM
- assert(system == oldContext->getSystemPtr());
-#else
- assert(process == oldContext->getProcessPtr());
-#endif
-
- // copy over functional state
- _status = oldContext->status();
- copyArchRegs(oldContext);
- cpu_id = oldContext->readCpuId();
-#if !FULL_SYSTEM
- func_exe_inst = oldContext->readFuncExeInst();
-#else
- EndQuiesceEvent *quiesce = oldContext->getQuiesceEvent();
- if (quiesce) {
- // Point the quiesce event's XC at this XC so that it wakes up
- // the proper CPU.
- quiesce->xc = proxy;
- }
- if (quiesceEvent) {
- quiesceEvent->xc = proxy;
- }
-#endif
-
- storeCondFailures = 0;
-
- oldContext->setStatus(ExecContext::Unallocated);
-}
-
-void
-CPUExecContext::serialize(ostream &os)
-{
- SERIALIZE_ENUM(_status);
- regs.serialize(os);
- // thread_num and cpu_id are deterministic from the config
- SERIALIZE_SCALAR(func_exe_inst);
- SERIALIZE_SCALAR(inst);
-
-#if FULL_SYSTEM
- Tick quiesceEndTick = 0;
- if (quiesceEvent->scheduled())
- quiesceEndTick = quiesceEvent->when();
- SERIALIZE_SCALAR(quiesceEndTick);
- if (kernelStats)
- kernelStats->serialize(os);
-#endif
-}
-
-
-void
-CPUExecContext::unserialize(Checkpoint *cp, const std::string &section)
-{
- UNSERIALIZE_ENUM(_status);
- regs.unserialize(cp, section);
- // thread_num and cpu_id are deterministic from the config
- UNSERIALIZE_SCALAR(func_exe_inst);
- UNSERIALIZE_SCALAR(inst);
-
-#if FULL_SYSTEM
- Tick quiesceEndTick;
- UNSERIALIZE_SCALAR(quiesceEndTick);
- if (quiesceEndTick)
- quiesceEvent->schedule(quiesceEndTick);
- if (kernelStats)
- kernelStats->unserialize(cp, section);
-#endif
-}
-
-
-void
-CPUExecContext::activate(int delay)
-{
- if (status() == ExecContext::Active)
- return;
-
- lastActivate = curTick;
-
- if (status() == ExecContext::Unallocated) {
- cpu->activateWhenReady(thread_num);
- return;
- }
-
- _status = ExecContext::Active;
-
- // status() == Suspended
- cpu->activateContext(thread_num, delay);
-}
-
-void
-CPUExecContext::suspend()
-{
- if (status() == ExecContext::Suspended)
- return;
-
- lastActivate = curTick;
- lastSuspend = curTick;
-/*
-#if FULL_SYSTEM
- // Don't change the status from active if there are pending interrupts
- if (cpu->check_interrupts()) {
- assert(status() == ExecContext::Active);
- return;
- }
-#endif
-*/
- _status = ExecContext::Suspended;
- cpu->suspendContext(thread_num);
-}
-
-void
-CPUExecContext::deallocate()
-{
- if (status() == ExecContext::Unallocated)
- return;
-
- _status = ExecContext::Unallocated;
- cpu->deallocateContext(thread_num);
-}
-
-void
-CPUExecContext::halt()
-{
- if (status() == ExecContext::Halted)
- return;
-
- _status = ExecContext::Halted;
- cpu->haltContext(thread_num);
-}
-
-
-void
-CPUExecContext::regStats(const string &name)
-{
-#if FULL_SYSTEM
- if (kernelStats)
- kernelStats->regStats(name + ".kern");
-#endif
-}
-
-void
-CPUExecContext::copyArchRegs(ExecContext *xc)
-{
- // First loop through the integer registers.
- for (int i = 0; i < AlphaISA::NumIntRegs; ++i) {
- setIntReg(i, xc->readIntReg(i));
- }
-
- // Then loop through the floating point registers.
- for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) {
- setFloatRegDouble(i, xc->readFloatRegDouble(i));
- setFloatRegInt(i, xc->readFloatRegInt(i));
- }
-
- // Copy misc. registers
- regs.miscRegs.copyMiscRegs(xc);
-
- // Lastly copy PC/NPC
- setPC(xc->readPC());
- setNextPC(xc->readNextPC());
-}
-
diff --git a/cpu/cpu_exec_context.hh b/cpu/cpu_exec_context.hh
deleted file mode 100644
index 061fe450a..000000000
--- a/cpu/cpu_exec_context.hh
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- * Copyright (c) 2001-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_CPU_EXEC_CONTEXT_HH__
-#define __CPU_CPU_EXEC_CONTEXT_HH__
-
-#include "arch/isa_traits.hh"
-#include "config/full_system.hh"
-#include "cpu/exec_context.hh"
-#include "mem/functional/functional.hh"
-#include "mem/mem_req.hh"
-#include "sim/byteswap.hh"
-#include "sim/eventq.hh"
-#include "sim/host.hh"
-#include "sim/serialize.hh"
-
-// forward declaration: see functional_memory.hh
-class FunctionalMemory;
-class PhysicalMemory;
-class BaseCPU;
-
-#if FULL_SYSTEM
-
-#include "sim/system.hh"
-#include "arch/tlb.hh"
-
-class FunctionProfile;
-class ProfileNode;
-class MemoryController;
-
-namespace Kernel {
- class Statistics;
-};
-
-#else // !FULL_SYSTEM
-
-#include "sim/process.hh"
-
-#endif // FULL_SYSTEM
-
-//
-// The CPUExecContext object represents a functional context for
-// instruction execution. It incorporates everything required for
-// architecture-level functional simulation of a single thread.
-//
-
-class CPUExecContext
-{
- protected:
- typedef TheISA::RegFile RegFile;
- typedef TheISA::MachInst MachInst;
- typedef TheISA::MiscRegFile MiscRegFile;
- typedef TheISA::MiscReg MiscReg;
- public:
- typedef ExecContext::Status Status;
-
- private:
- Status _status;
-
- public:
- Status status() const { return _status; }
-
- void setStatus(Status newStatus) { _status = newStatus; }
-
- /// Set the status to Active. Optional delay indicates number of
- /// cycles to wait before beginning execution.
- void activate(int delay = 1);
-
- /// Set the status to Suspended.
- void suspend();
-
- /// Set the status to Unallocated.
- void deallocate();
-
- /// Set the status to Halted.
- void halt();
-
- protected:
- RegFile regs; // correct-path register context
-
- public:
- // pointer to CPU associated with this context
- BaseCPU *cpu;
-
- ProxyExecContext<CPUExecContext> *proxy;
-
- // Current instruction
- MachInst inst;
-
- // Index of hardware thread context on the CPU that this represents.
- int thread_num;
-
- // ID of this context w.r.t. the System or Process object to which
- // it belongs. For full-system mode, this is the system CPU ID.
- int cpu_id;
-
- Tick lastActivate;
- Tick lastSuspend;
-
-#if FULL_SYSTEM
- FunctionalMemory *mem;
- AlphaITB *itb;
- AlphaDTB *dtb;
- System *system;
-
- // the following two fields are redundant, since we can always
- // look them up through the system pointer, but we'll leave them
- // here for now for convenience
- MemoryController *memctrl;
- PhysicalMemory *physmem;
-
- FunctionProfile *profile;
- ProfileNode *profileNode;
- Addr profilePC;
- void dumpFuncProfile();
-
- EndQuiesceEvent *quiesceEvent;
-
- EndQuiesceEvent *getQuiesceEvent() { return quiesceEvent; }
-
- Tick readLastActivate() { return lastActivate; }
-
- Tick readLastSuspend() { return lastSuspend; }
-
- void profileClear();
-
- void profileSample();
-
- Kernel::Statistics *getKernelStats() { return kernelStats; }
-
- Kernel::Statistics *kernelStats;
-#else
- Process *process;
-
- FunctionalMemory *mem; // functional storage for process address space
-
- // Address space ID. Note that this is used for TIMING cache
- // simulation only; all functional memory accesses should use
- // one of the FunctionalMemory pointers above.
- short asid;
-
-#endif
-
- /**
- * Temporary storage to pass the source address from copy_load to
- * copy_store.
- * @todo Remove this temporary when we have a better way to do it.
- */
- Addr copySrcAddr;
- /**
- * Temp storage for the physical source address of a copy.
- * @todo Remove this temporary when we have a better way to do it.
- */
- Addr copySrcPhysAddr;
-
-
- /*
- * number of executed instructions, for matching with syscall trace
- * points in EIO files.
- */
- Counter func_exe_inst;
-
- //
- // Count failed store conditionals so we can warn of apparent
- // application deadlock situations.
- unsigned storeCondFailures;
-
- // constructor: initialize context from given process structure
-#if FULL_SYSTEM
- CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
- AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_mem,
- bool use_kernel_stats = true);
-#else
- CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid);
- CPUExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem,
- int _asid);
- // Constructor to use XC to pass reg file around. Not used for anything
- // else.
- CPUExecContext(RegFile *regFile);
-#endif
- virtual ~CPUExecContext();
-
- virtual void takeOverFrom(ExecContext *oldContext);
-
- void regStats(const std::string &name);
-
- void serialize(std::ostream &os);
- void unserialize(Checkpoint *cp, const std::string &section);
-
- BaseCPU *getCpuPtr() { return cpu; }
-
- ExecContext *getProxy() { return proxy; }
-
- int getThreadNum() { return thread_num; }
-
-#if FULL_SYSTEM
- System *getSystemPtr() { return system; }
-
- PhysicalMemory *getPhysMemPtr() { return physmem; }
-
- AlphaITB *getITBPtr() { return itb; }
-
- AlphaDTB *getDTBPtr() { return dtb; }
-
- bool validInstAddr(Addr addr) { return true; }
- bool validDataAddr(Addr addr) { return true; }
- int getInstAsid() { return regs.instAsid(); }
- int getDataAsid() { return regs.dataAsid(); }
-
- Fault translateInstReq(MemReqPtr &req)
- {
- return itb->translate(req);
- }
-
- Fault translateDataReadReq(MemReqPtr &req)
- {
- return dtb->translate(req, false);
- }
-
- Fault translateDataWriteReq(MemReqPtr &req)
- {
- return dtb->translate(req, true);
- }
-
-#else
- Process *getProcessPtr() { return process; }
-
- bool validInstAddr(Addr addr)
- { return process->validInstAddr(addr); }
-
- bool validDataAddr(Addr addr)
- { return process->validDataAddr(addr); }
-
- int getInstAsid() { return asid; }
- int getDataAsid() { return asid; }
-
- Fault dummyTranslation(MemReqPtr &req)
- {
-#if 0
- assert((req->vaddr >> 48 & 0xffff) == 0);
-#endif
-
- // put the asid in the upper 16 bits of the paddr
- req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
- req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
- return NoFault;
- }
- Fault translateInstReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
- Fault translateDataReadReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
- Fault translateDataWriteReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
-
-#endif
-
- template <class T>
- Fault read(MemReqPtr &req, T &data)
- {
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
- if (req->flags & LOCKED) {
- req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
- req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
- }
-#endif
-
- Fault error;
- error = mem->read(req, data);
- data = LittleEndianGuest::gtoh(data);
- return error;
- }
-
- template <class T>
- Fault write(MemReqPtr &req, T &data)
- {
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
- ExecContext *xc;
-
- // If this is a store conditional, act appropriately
- if (req->flags & LOCKED) {
- xc = req->xc;
-
- if (req->flags & UNCACHEABLE) {
- // Don't update result register (see stq_c in isa_desc)
- req->result = 2;
- xc->setStCondFailures(0);//Needed? [RGD]
- } else {
- bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag);
- Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag);
- req->result = lock_flag;
- if (!lock_flag ||
- ((lock_addr & ~0xf) != (req->paddr & ~0xf))) {
- xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
- xc->setStCondFailures(xc->readStCondFailures() + 1);
- if (((xc->readStCondFailures()) % 100000) == 0) {
- std::cerr << "Warning: "
- << xc->readStCondFailures()
- << " consecutive store conditional failures "
- << "on cpu " << req->xc->readCpuId()
- << std::endl;
- }
- return NoFault;
- }
- else xc->setStCondFailures(0);
- }
- }
-
- // Need to clear any locked flags on other proccessors for
- // this address. Only do this for succsful Store Conditionals
- // and all other stores (WH64?). Unsuccessful Store
- // Conditionals would have returned above, and wouldn't fall
- // through.
- for (int i = 0; i < system->execContexts.size(); i++){
- xc = system->execContexts[i];
- if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
- (req->paddr & ~0xf)) {
- xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
- }
- }
-
-#endif
- return mem->write(req, (T)LittleEndianGuest::htog(data));
- }
-
- virtual bool misspeculating();
-
-
- MachInst getInst() { return inst; }
-
- void setInst(MachInst new_inst)
- {
- inst = new_inst;
- }
-
- Fault instRead(MemReqPtr &req)
- {
- return mem->read(req, inst);
- }
-
- void setCpuId(int id) { cpu_id = id; }
-
- int readCpuId() { return cpu_id; }
-
- FunctionalMemory *getMemPtr() { return mem; }
-
- void copyArchRegs(ExecContext *xc);
-
- //
- // New accessors for new decoder.
- //
- uint64_t readIntReg(int reg_idx)
- {
- return regs.intRegFile[reg_idx];
- }
-
- float readFloatRegSingle(int reg_idx)
- {
- return (float)regs.floatRegFile.d[reg_idx];
- }
-
- double readFloatRegDouble(int reg_idx)
- {
- return regs.floatRegFile.d[reg_idx];
- }
-
- uint64_t readFloatRegInt(int reg_idx)
- {
- return regs.floatRegFile.q[reg_idx];
- }
-
- void setIntReg(int reg_idx, uint64_t val)
- {
- regs.intRegFile[reg_idx] = val;
- }
-
- void setFloatRegSingle(int reg_idx, float val)
- {
- regs.floatRegFile.d[reg_idx] = (double)val;
- }
-
- void setFloatRegDouble(int reg_idx, double val)
- {
- regs.floatRegFile.d[reg_idx] = val;
- }
-
- void setFloatRegInt(int reg_idx, uint64_t val)
- {
- regs.floatRegFile.q[reg_idx] = val;
- }
-
- uint64_t readPC()
- {
- return regs.pc;
- }
-
- void setPC(uint64_t val)
- {
- regs.pc = val;
- }
-
- uint64_t readNextPC()
- {
- return regs.npc;
- }
-
- void setNextPC(uint64_t val)
- {
- regs.npc = val;
- }
-
- uint64_t readNextNPC()
- {
- return regs.nnpc;
- }
-
- void setNextNPC(uint64_t val)
- {
- regs.nnpc = val;
- }
-
-
- MiscReg readMiscReg(int misc_reg)
- {
- return regs.miscRegs.readReg(misc_reg);
- }
-
- MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
- {
- return regs.miscRegs.readRegWithEffect(misc_reg, fault, proxy);
- }
-
- Fault setMiscReg(int misc_reg, const MiscReg &val)
- {
- return regs.miscRegs.setReg(misc_reg, val);
- }
-
- Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
- {
- return regs.miscRegs.setRegWithEffect(misc_reg, val, proxy);
- }
-
- unsigned readStCondFailures() { return storeCondFailures; }
-
- void setStCondFailures(unsigned sc_failures)
- { storeCondFailures = sc_failures; }
-
- void clearArchRegs() { memset(&regs, 0, sizeof(regs)); }
-
-#if FULL_SYSTEM
- int readIntrFlag() { return regs.intrflag; }
- void setIntrFlag(int val) { regs.intrflag = val; }
- Fault hwrei();
- bool inPalMode() { return AlphaISA::PcPAL(regs.pc); }
- bool simPalCheck(int palFunc);
-#endif
-
-#if !FULL_SYSTEM
- TheISA::IntReg getSyscallArg(int i)
- {
- return regs.intRegFile[TheISA::ArgumentReg0 + i];
- }
-
- // used to shift args for indirect syscall
- void setSyscallArg(int i, TheISA::IntReg val)
- {
- regs.intRegFile[TheISA::ArgumentReg0 + i] = val;
- }
-
- void setSyscallReturn(SyscallReturn return_value)
- {
- TheISA::setSyscallReturn(return_value, &regs);
- }
-
- void syscall()
- {
- process->syscall(proxy);
- }
-
- Counter readFuncExeInst() { return func_exe_inst; }
-
- void setFuncExeInst(Counter new_val) { func_exe_inst = new_val; }
-#endif
-};
-
-
-// for non-speculative execution context, spec_mode is always false
-inline bool
-CPUExecContext::misspeculating()
-{
- return false;
-}
-
-#endif // __CPU_CPU_EXEC_CONTEXT_HH__
diff --git a/cpu/cpu_models.py b/cpu/cpu_models.py
deleted file mode 100644
index 2b1ae6277..000000000
--- a/cpu/cpu_models.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# Copyright (c) 2003-2006 The Regents of The University of Michigan
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-################
-# CpuModel class
-#
-# The CpuModel class encapsulates everything the ISA parser needs to
-# know about a particular CPU model.
-
-class CpuModel:
- # Dict of available CPU model objects. Accessible as CpuModel.dict.
- dict = {}
-
- # Constructor. Automatically adds models to CpuModel.dict.
- def __init__(self, name, filename, includes, strings):
- self.name = name
- self.filename = filename # filename for output exec code
- self.includes = includes # include files needed in exec file
- # The 'strings' dict holds all the per-CPU symbols we can
- # substitute into templates etc.
- self.strings = strings
- # Add self to dict
- CpuModel.dict[name] = self
-
-
-#
-# Define CPU models.
-#
-# Parameters are:
-# - name of model
-# - filename for generated ISA execution file
-# - includes needed for generated ISA execution file
-# - substitution strings for ISA description templates
-#
-
-CpuModel('SimpleCPU', 'simple_cpu_exec.cc',
- '#include "cpu/simple/cpu.hh"',
- { 'CPU_exec_context': 'SimpleCPU' })
-CpuModel('FastCPU', 'fast_cpu_exec.cc',
- '#include "cpu/fast/cpu.hh"',
- { 'CPU_exec_context': 'FastCPU' })
-CpuModel('FullCPU', 'full_cpu_exec.cc',
- '#include "encumbered/cpu/full/dyn_inst.hh"',
- { 'CPU_exec_context': 'DynInst' })
-CpuModel('AlphaFullCPU', 'alpha_o3_exec.cc',
- '#include "cpu/o3/alpha_dyn_inst.hh"',
- { 'CPU_exec_context': 'AlphaDynInst<AlphaSimpleImpl>' })
-CpuModel('OzoneSimpleCPU', 'ozone_simple_exec.cc',
- '#include "cpu/ozone/dyn_inst.hh"',
- { 'CPU_exec_context': 'OzoneDynInst<SimpleImpl>' })
-CpuModel('OzoneCPU', 'ozone_exec.cc',
- '#include "cpu/ozone/dyn_inst.hh"',
- { 'CPU_exec_context': 'OzoneDynInst<OzoneImpl>' })
-CpuModel('CheckerCPU', 'checker_cpu_exec.cc',
- '#include "cpu/checker/cpu.hh"',
- { 'CPU_exec_context': 'CheckerCPU' })
-
diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh
deleted file mode 100644
index e1f1016e5..000000000
--- a/cpu/exec_context.hh
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_EXEC_CONTEXT_HH__
-#define __CPU_EXEC_CONTEXT_HH__
-
-#include "config/full_system.hh"
-#include "mem/mem_req.hh"
-#include "sim/faults.hh"
-#include "sim/host.hh"
-#include "sim/serialize.hh"
-#include "sim/byteswap.hh"
-
-// forward declaration: see functional_memory.hh
-// @todo: Figure out a more architecture independent way to obtain the ITB and
-// DTB pointers.
-class AlphaDTB;
-class AlphaITB;
-class BaseCPU;
-class EndQuiesceEvent;
-class Event;
-class FunctionalMemory;
-class PhysicalMemory;
-class Process;
-class System;
-namespace Kernel {
- class Statistics;
-};
-
-class ExecContext
-{
- protected:
- typedef TheISA::RegFile RegFile;
- typedef TheISA::MachInst MachInst;
- typedef TheISA::IntReg IntReg;
- typedef TheISA::MiscRegFile MiscRegFile;
- typedef TheISA::MiscReg MiscReg;
- public:
- enum Status
- {
- /// Initialized but not running yet. All CPUs start in
- /// this state, but most transition to Active on cycle 1.
- /// In MP or SMT systems, non-primary contexts will stay
- /// in this state until a thread is assigned to them.
- Unallocated,
-
- /// Running. Instructions should be executed only when
- /// the context is in this state.
- Active,
-
- /// Temporarily inactive. Entered while waiting for
- /// synchronization, etc.
- Suspended,
-
- /// Permanently shut down. Entered when target executes
- /// m5exit pseudo-instruction. When all contexts enter
- /// this state, the simulation will terminate.
- Halted
- };
-
- virtual ~ExecContext() { };
-
- virtual BaseCPU *getCpuPtr() = 0;
-
- virtual void setCpuId(int id) = 0;
-
- virtual int readCpuId() = 0;
-
- virtual FunctionalMemory *getMemPtr() = 0;
-
-#if FULL_SYSTEM
- virtual System *getSystemPtr() = 0;
-
- virtual PhysicalMemory *getPhysMemPtr() = 0;
-
- virtual AlphaITB *getITBPtr() = 0;
-
- virtual AlphaDTB * getDTBPtr() = 0;
-
- virtual Kernel::Statistics *getKernelStats() = 0;
-#else
- virtual Process *getProcessPtr() = 0;
-#endif
-
- virtual Status status() const = 0;
-
- virtual void setStatus(Status new_status) = 0;
-
- /// Set the status to Active. Optional delay indicates number of
- /// cycles to wait before beginning execution.
- virtual void activate(int delay = 1) = 0;
-
- /// Set the status to Suspended.
- virtual void suspend() = 0;
-
- /// Set the status to Unallocated.
- virtual void deallocate() = 0;
-
- /// Set the status to Halted.
- virtual void halt() = 0;
-
-#if FULL_SYSTEM
- virtual void dumpFuncProfile() = 0;
-#endif
-
- virtual void takeOverFrom(ExecContext *old_context) = 0;
-
- virtual void regStats(const std::string &name) = 0;
-
- virtual void serialize(std::ostream &os) = 0;
- virtual void unserialize(Checkpoint *cp, const std::string &section) = 0;
-
-#if FULL_SYSTEM
- virtual EndQuiesceEvent *getQuiesceEvent() = 0;
-
- // Not necessarily the best location for these...
- // Having an extra function just to read these is obnoxious
- virtual Tick readLastActivate() = 0;
- virtual Tick readLastSuspend() = 0;
-
- virtual void profileClear() = 0;
- virtual void profileSample() = 0;
-#endif
-
- virtual int getThreadNum() = 0;
-
- // Also somewhat obnoxious. Really only used for the TLB fault.
- // However, may be quite useful in SPARC.
- virtual TheISA::MachInst getInst() = 0;
-
- virtual void copyArchRegs(ExecContext *xc) = 0;
-
- virtual void clearArchRegs() = 0;
-
- //
- // New accessors for new decoder.
- //
- virtual uint64_t readIntReg(int reg_idx) = 0;
-
- virtual float readFloatRegSingle(int reg_idx) = 0;
-
- virtual double readFloatRegDouble(int reg_idx) = 0;
-
- virtual uint64_t readFloatRegInt(int reg_idx) = 0;
-
- virtual void setIntReg(int reg_idx, uint64_t val) = 0;
-
- virtual void setFloatRegSingle(int reg_idx, float val) = 0;
-
- virtual void setFloatRegDouble(int reg_idx, double val) = 0;
-
- virtual void setFloatRegInt(int reg_idx, uint64_t val) = 0;
-
- virtual uint64_t readPC() = 0;
-
- virtual void setPC(uint64_t val) = 0;
-
- virtual uint64_t readNextPC() = 0;
-
- virtual void setNextPC(uint64_t val) = 0;
-
- virtual MiscReg readMiscReg(int misc_reg) = 0;
-
- virtual MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) = 0;
-
- virtual Fault setMiscReg(int misc_reg, const MiscReg &val) = 0;
-
- virtual Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) = 0;
-
- // Also not necessarily the best location for these two. Hopefully will go
- // away once we decide upon where st cond failures goes.
- virtual unsigned readStCondFailures() = 0;
-
- virtual void setStCondFailures(unsigned sc_failures) = 0;
-
-#if FULL_SYSTEM
- virtual bool inPalMode() = 0;
-#endif
-
- // Only really makes sense for old CPU model. Still could be useful though.
- virtual bool misspeculating() = 0;
-
-#if !FULL_SYSTEM
- virtual IntReg getSyscallArg(int i) = 0;
-
- // used to shift args for indirect syscall
- virtual void setSyscallArg(int i, IntReg val) = 0;
-
- virtual void setSyscallReturn(SyscallReturn return_value) = 0;
-
-// virtual void syscall() = 0;
-
- // Same with st cond failures.
- virtual Counter readFuncExeInst() = 0;
-#endif
-};
-
-template <class XC>
-class ProxyExecContext : public ExecContext
-{
- public:
- ProxyExecContext(XC *actual_xc)
- { actualXC = actual_xc; }
-
- private:
- XC *actualXC;
-
- public:
-
- BaseCPU *getCpuPtr() { return actualXC->getCpuPtr(); }
-
- void setCpuId(int id) { actualXC->setCpuId(id); }
-
- int readCpuId() { return actualXC->readCpuId(); }
-
- FunctionalMemory *getMemPtr() { return actualXC->getMemPtr(); }
-
-#if FULL_SYSTEM
- System *getSystemPtr() { return actualXC->getSystemPtr(); }
-
- PhysicalMemory *getPhysMemPtr() { return actualXC->getPhysMemPtr(); }
-
- AlphaITB *getITBPtr() { return actualXC->getITBPtr(); }
-
- AlphaDTB *getDTBPtr() { return actualXC->getDTBPtr(); }
-
- Kernel::Statistics *getKernelStats() { return actualXC->getKernelStats(); }
-#else
- Process *getProcessPtr() { return actualXC->getProcessPtr(); }
-#endif
-
- Status status() const { return actualXC->status(); }
-
- void setStatus(Status new_status) { actualXC->setStatus(new_status); }
-
- /// Set the status to Active. Optional delay indicates number of
- /// cycles to wait before beginning execution.
- void activate(int delay = 1) { actualXC->activate(delay); }
-
- /// Set the status to Suspended.
- void suspend() { actualXC->suspend(); }
-
- /// Set the status to Unallocated.
- void deallocate() { actualXC->deallocate(); }
-
- /// Set the status to Halted.
- void halt() { actualXC->halt(); }
-
-#if FULL_SYSTEM
- void dumpFuncProfile() { actualXC->dumpFuncProfile(); }
-#endif
-
- void takeOverFrom(ExecContext *oldContext)
- { actualXC->takeOverFrom(oldContext); }
-
- void regStats(const std::string &name) { actualXC->regStats(name); }
-
- void serialize(std::ostream &os) { actualXC->serialize(os); }
- void unserialize(Checkpoint *cp, const std::string &section)
- { actualXC->unserialize(cp, section); }
-
-#if FULL_SYSTEM
- EndQuiesceEvent *getQuiesceEvent() { return actualXC->getQuiesceEvent(); }
-
- Tick readLastActivate() { return actualXC->readLastActivate(); }
- Tick readLastSuspend() { return actualXC->readLastSuspend(); }
-
- void profileClear() { return actualXC->profileClear(); }
- void profileSample() { return actualXC->profileSample(); }
-#endif
-
- int getThreadNum() { return actualXC->getThreadNum(); }
-
- // @todo: Do I need this?
- MachInst getInst() { return actualXC->getInst(); }
-
- // @todo: Do I need this?
- void copyArchRegs(ExecContext *xc) { actualXC->copyArchRegs(xc); }
-
- void clearArchRegs() { actualXC->clearArchRegs(); }
-
- //
- // New accessors for new decoder.
- //
- uint64_t readIntReg(int reg_idx)
- { return actualXC->readIntReg(reg_idx); }
-
- float readFloatRegSingle(int reg_idx)
- { return actualXC->readFloatRegSingle(reg_idx); }
-
- double readFloatRegDouble(int reg_idx)
- { return actualXC->readFloatRegDouble(reg_idx); }
-
- uint64_t readFloatRegInt(int reg_idx)
- { return actualXC->readFloatRegInt(reg_idx); }
-
- void setIntReg(int reg_idx, uint64_t val)
- { actualXC->setIntReg(reg_idx, val); }
-
- void setFloatRegSingle(int reg_idx, float val)
- { actualXC->setFloatRegSingle(reg_idx, val); }
-
- void setFloatRegDouble(int reg_idx, double val)
- { actualXC->setFloatRegDouble(reg_idx, val); }
-
- void setFloatRegInt(int reg_idx, uint64_t val)
- { actualXC->setFloatRegInt(reg_idx, val); }
-
- uint64_t readPC() { return actualXC->readPC(); }
-
- void setPC(uint64_t val) { actualXC->setPC(val); }
-
- uint64_t readNextPC() { return actualXC->readNextPC(); }
-
- void setNextPC(uint64_t val) { actualXC->setNextPC(val); }
-
- MiscReg readMiscReg(int misc_reg)
- { return actualXC->readMiscReg(misc_reg); }
-
- MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
- { return actualXC->readMiscRegWithEffect(misc_reg, fault); }
-
- Fault setMiscReg(int misc_reg, const MiscReg &val)
- { return actualXC->setMiscReg(misc_reg, val); }
-
- Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
- { return actualXC->setMiscRegWithEffect(misc_reg, val); }
-
- unsigned readStCondFailures()
- { return actualXC->readStCondFailures(); }
-
- void setStCondFailures(unsigned sc_failures)
- { actualXC->setStCondFailures(sc_failures); }
-#if FULL_SYSTEM
- bool inPalMode() { return actualXC->inPalMode(); }
-#endif
-
- // @todo: Fix this!
- bool misspeculating() { return actualXC->misspeculating(); }
-
-#if !FULL_SYSTEM
- IntReg getSyscallArg(int i) { return actualXC->getSyscallArg(i); }
-
- // used to shift args for indirect syscall
- void setSyscallArg(int i, IntReg val)
- { actualXC->setSyscallArg(i, val); }
-
- void setSyscallReturn(SyscallReturn return_value)
- { actualXC->setSyscallReturn(return_value); }
-
-// void syscall() { actualXC->syscall(); }
-
- Counter readFuncExeInst() { return actualXC->readFuncExeInst(); }
-#endif
-};
-
-#endif
diff --git a/cpu/exetrace.cc b/cpu/exetrace.cc
deleted file mode 100644
index d5eacd839..000000000
--- a/cpu/exetrace.cc
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <fstream>
-#include <iomanip>
-
-#include "sim/param.hh"
-#include "encumbered/cpu/full/dyn_inst.hh"
-#include "encumbered/cpu/full/spec_state.hh"
-#include "encumbered/cpu/full/issue.hh"
-#include "cpu/exetrace.hh"
-#include "base/loader/symtab.hh"
-#include "cpu/base.hh"
-#include "cpu/static_inst.hh"
-
-using namespace std;
-
-
-////////////////////////////////////////////////////////////////////////
-//
-// Methods for the InstRecord object
-//
-
-
-void
-Trace::InstRecord::dump(ostream &outs)
-{
- if (flags[INTEL_FORMAT]) {
-#if FULL_SYSTEM
- bool is_trace_system = (cpu->system->name() == trace_system);
-#else
- bool is_trace_system = true;
-#endif
- if (is_trace_system) {
- ccprintf(outs, "%7d ) ", cycle);
- outs << "0x" << hex << PC << ":\t";
- if (staticInst->isLoad()) {
- outs << "<RD 0x" << hex << addr;
- outs << ">";
- } else if (staticInst->isStore()) {
- outs << "<WR 0x" << hex << addr;
- outs << ">";
- }
- outs << endl;
- }
- } else {
- if (flags[PRINT_CYCLE])
- ccprintf(outs, "%7d: ", cycle);
-
- outs << cpu->name() << " ";
-
- if (flags[TRACE_MISSPEC])
- outs << (misspeculating ? "-" : "+") << " ";
-
- if (flags[PRINT_THREAD_NUM])
- outs << "T" << thread << " : ";
-
-
- std::string sym_str;
- Addr sym_addr;
- if (debugSymbolTable
- && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr)
- && flags[PC_SYMBOL]) {
- if (PC != sym_addr)
- sym_str += csprintf("+%d", PC - sym_addr);
- outs << "@" << sym_str << " : ";
- }
- else {
- outs << "0x" << hex << PC << " : ";
- }
-
- //
- // Print decoded instruction
- //
-
-#if defined(__GNUC__) && (__GNUC__ < 3)
- // There's a bug in gcc 2.x library that prevents setw()
- // from working properly on strings
- string mc(staticInst->disassemble(PC, debugSymbolTable));
- while (mc.length() < 26)
- mc += " ";
- outs << mc;
-#else
- outs << setw(26) << left << staticInst->disassemble(PC, debugSymbolTable);
-#endif
-
- outs << " : ";
-
- if (flags[PRINT_OP_CLASS]) {
- outs << opClassStrings[staticInst->opClass()] << " : ";
- }
-
- if (flags[PRINT_RESULT_DATA] && data_status != DataInvalid) {
- outs << " D=";
-#if 0
- if (data_status == DataDouble)
- ccprintf(outs, "%f", data.as_double);
- else
- ccprintf(outs, "%#018x", data.as_int);
-#else
- ccprintf(outs, "%#018x", data.as_int);
-#endif
- }
-
- if (flags[PRINT_EFF_ADDR] && addr_valid)
- outs << " A=0x" << hex << addr;
-
- if (flags[PRINT_INT_REGS] && regs_valid) {
- for (int i = 0; i < 32;)
- for (int j = i + 1; i <= j; i++)
- ccprintf(outs, "r%02d = %#018x%s", i, iregs->regs[i],
- ((i == j) ? "\n" : " "));
- outs << "\n";
- }
-
- if (flags[PRINT_FETCH_SEQ] && fetch_seq_valid)
- outs << " FetchSeq=" << dec << fetch_seq;
-
- if (flags[PRINT_CP_SEQ] && cp_seq_valid)
- outs << " CPSeq=" << dec << cp_seq;
-
- //
- // End of line...
- //
- outs << endl;
- }
-}
-
-
-vector<bool> Trace::InstRecord::flags(NUM_BITS);
-string Trace::InstRecord::trace_system;
-
-////////////////////////////////////////////////////////////////////////
-//
-// Parameter space for per-cycle execution address tracing options.
-// Derive from ParamContext so we can override checkParams() function.
-//
-class ExecutionTraceParamContext : public ParamContext
-{
- public:
- ExecutionTraceParamContext(const string &_iniSection)
- : ParamContext(_iniSection)
- {
- }
-
- void checkParams(); // defined at bottom of file
-};
-
-ExecutionTraceParamContext exeTraceParams("exetrace");
-
-Param<bool> exe_trace_spec(&exeTraceParams, "speculative",
- "capture speculative instructions", true);
-
-Param<bool> exe_trace_print_cycle(&exeTraceParams, "print_cycle",
- "print cycle number", true);
-Param<bool> exe_trace_print_opclass(&exeTraceParams, "print_opclass",
- "print op class", true);
-Param<bool> exe_trace_print_thread(&exeTraceParams, "print_thread",
- "print thread number", true);
-Param<bool> exe_trace_print_effaddr(&exeTraceParams, "print_effaddr",
- "print effective address", true);
-Param<bool> exe_trace_print_data(&exeTraceParams, "print_data",
- "print result data", true);
-Param<bool> exe_trace_print_iregs(&exeTraceParams, "print_iregs",
- "print all integer regs", false);
-Param<bool> exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq",
- "print fetch sequence number", false);
-Param<bool> exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq",
- "print correct-path sequence number", false);
-Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol",
- "Use symbols for the PC if available", true);
-Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format",
- "print trace in intel compatible format", false);
-Param<string> exe_trace_system(&exeTraceParams, "trace_system",
- "print trace of which system (client or server)",
- "client");
-
-
-//
-// Helper function for ExecutionTraceParamContext::checkParams() just
-// to get us into the InstRecord namespace
-//
-void
-Trace::InstRecord::setParams()
-{
- flags[TRACE_MISSPEC] = exe_trace_spec;
-
- flags[PRINT_CYCLE] = exe_trace_print_cycle;
- flags[PRINT_OP_CLASS] = exe_trace_print_opclass;
- flags[PRINT_THREAD_NUM] = exe_trace_print_thread;
- flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr;
- flags[PRINT_EFF_ADDR] = exe_trace_print_data;
- flags[PRINT_INT_REGS] = exe_trace_print_iregs;
- flags[PRINT_FETCH_SEQ] = exe_trace_print_fetchseq;
- flags[PRINT_CP_SEQ] = exe_trace_print_cp_seq;
- flags[PC_SYMBOL] = exe_trace_pc_symbol;
- flags[INTEL_FORMAT] = exe_trace_intel_format;
- trace_system = exe_trace_system;
-}
-
-void
-ExecutionTraceParamContext::checkParams()
-{
- Trace::InstRecord::setParams();
-}
-
diff --git a/cpu/exetrace.hh b/cpu/exetrace.hh
deleted file mode 100644
index 2f70e26e7..000000000
--- a/cpu/exetrace.hh
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __EXETRACE_HH__
-#define __EXETRACE_HH__
-
-#include <fstream>
-#include <vector>
-
-#include "sim/host.hh"
-#include "cpu/inst_seq.hh" // for InstSeqNum
-#include "base/trace.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/static_inst.hh"
-
-class BaseCPU;
-
-
-namespace Trace {
-
-class InstRecord : public Record
-{
- protected:
- typedef TheISA::IntRegFile IntRegFile;
-
- // The following fields are initialized by the constructor and
- // thus guaranteed to be valid.
- BaseCPU *cpu;
- // need to make this ref-counted so it doesn't go away before we
- // dump the record
- StaticInstPtr staticInst;
- Addr PC;
- bool misspeculating;
- unsigned thread;
-
- // The remaining fields are only valid for particular instruction
- // types (e.g, addresses for memory ops) or when particular
- // options are enabled (e.g., tracing full register contents).
- // Each data field has an associated valid flag to indicate
- // whether the data field is valid.
- Addr addr;
- bool addr_valid;
-
- union {
- uint64_t as_int;
- double as_double;
- } data;
- enum {
- DataInvalid = 0,
- DataInt8 = 1, // set to equal number of bytes
- DataInt16 = 2,
- DataInt32 = 4,
- DataInt64 = 8,
- DataDouble = 3
- } data_status;
-
- InstSeqNum fetch_seq;
- bool fetch_seq_valid;
-
- InstSeqNum cp_seq;
- bool cp_seq_valid;
-
- struct iRegFile {
- IntRegFile regs;
- };
- iRegFile *iregs;
- bool regs_valid;
-
- public:
- InstRecord(Tick _cycle, BaseCPU *_cpu,
- const StaticInstPtr &_staticInst,
- Addr _pc, bool spec, int _thread)
- : Record(_cycle), cpu(_cpu), staticInst(_staticInst), PC(_pc),
- misspeculating(spec), thread(_thread)
- {
- data_status = DataInvalid;
- addr_valid = false;
- regs_valid = false;
-
- fetch_seq_valid = false;
- cp_seq_valid = false;
- }
-
- virtual ~InstRecord() { }
-
- virtual void dump(std::ostream &outs);
-
- void setAddr(Addr a) { addr = a; addr_valid = true; }
-
- void setData(uint64_t d) { data.as_int = d; data_status = DataInt64; }
- void setData(uint32_t d) { data.as_int = d; data_status = DataInt32; }
- void setData(uint16_t d) { data.as_int = d; data_status = DataInt16; }
- void setData(uint8_t d) { data.as_int = d; data_status = DataInt8; }
-
- void setData(int64_t d) { setData((uint64_t)d); }
- void setData(int32_t d) { setData((uint32_t)d); }
- void setData(int16_t d) { setData((uint16_t)d); }
- void setData(int8_t d) { setData((uint8_t)d); }
-
- void setData(double d) { data.as_double = d; data_status = DataDouble; }
-
- void setFetchSeq(InstSeqNum seq)
- { fetch_seq = seq; fetch_seq_valid = true; }
-
- void setCPSeq(InstSeqNum seq)
- { cp_seq = seq; cp_seq_valid = true; }
-
- void setRegs(const IntRegFile &regs);
-
- void finalize() { theLog.append(this); }
-
- enum InstExecFlagBits {
- TRACE_MISSPEC = 0,
- PRINT_CYCLE,
- PRINT_OP_CLASS,
- PRINT_THREAD_NUM,
- PRINT_RESULT_DATA,
- PRINT_EFF_ADDR,
- PRINT_INT_REGS,
- PRINT_FETCH_SEQ,
- PRINT_CP_SEQ,
- PC_SYMBOL,
- INTEL_FORMAT,
- NUM_BITS
- };
-
- static std::vector<bool> flags;
- static std::string trace_system;
-
- static void setParams();
-
- static bool traceMisspec() { return flags[TRACE_MISSPEC]; }
-};
-
-
-inline void
-InstRecord::setRegs(const IntRegFile &regs)
-{
- if (!iregs)
- iregs = new iRegFile;
-
- memcpy(&iregs->regs, regs, sizeof(IntRegFile));
- regs_valid = true;
-}
-
-inline
-InstRecord *
-getInstRecord(Tick cycle, ExecContext *xc, BaseCPU *cpu,
- const StaticInstPtr staticInst,
- Addr pc, int thread = 0)
-{
- if (DTRACE(InstExec) &&
- (InstRecord::traceMisspec() || !xc->misspeculating())) {
- return new InstRecord(cycle, cpu, staticInst, pc,
- xc->misspeculating(), thread);
- }
-
- return NULL;
-}
-
-
-}
-
-#endif // __EXETRACE_HH__
diff --git a/cpu/inst_seq.hh b/cpu/inst_seq.hh
deleted file mode 100644
index 356d19df0..000000000
--- a/cpu/inst_seq.hh
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2001, 2003-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __STD_TYPES_HH__
-#define __STD_TYPES_HH__
-
-#include <stdint.h>
-
-// inst sequence type, used to order instructions in the ready list,
-// if this rolls over the ready list order temporarily will get messed
-// up, but execution will continue and complete correctly
-typedef uint64_t InstSeqNum;
-
-// inst tag type, used to tag an operation instance in the IQ
-typedef unsigned int InstTag;
-
-#endif // __STD_TYPES_HH__
diff --git a/cpu/intr_control.cc b/cpu/intr_control.cc
deleted file mode 100644
index 43e7f654c..000000000
--- a/cpu/intr_control.cc
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <string>
-#include <vector>
-
-#include "cpu/base.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/intr_control.hh"
-#include "sim/builder.hh"
-#include "sim/sim_object.hh"
-
-using namespace std;
-
-IntrControl::IntrControl(const string &name, BaseCPU *c)
- : SimObject(name), cpu(c)
-{}
-
-/* @todo
- *Fix the cpu sim object parameter to be a system pointer
- *instead, to avoid some extra dereferencing
- */
-void
-IntrControl::post(int int_num, int index)
-{
- std::vector<ExecContext *> &xcvec = cpu->system->execContexts;
- BaseCPU *temp = xcvec[0]->getCpuPtr();
- temp->post_interrupt(int_num, index);
-}
-
-void
-IntrControl::post(int cpu_id, int int_num, int index)
-{
- std::vector<ExecContext *> &xcvec = cpu->system->execContexts;
- BaseCPU *temp = xcvec[cpu_id]->getCpuPtr();
- temp->post_interrupt(int_num, index);
-}
-
-void
-IntrControl::clear(int int_num, int index)
-{
- std::vector<ExecContext *> &xcvec = cpu->system->execContexts;
- BaseCPU *temp = xcvec[0]->getCpuPtr();
- temp->clear_interrupt(int_num, index);
-}
-
-void
-IntrControl::clear(int cpu_id, int int_num, int index)
-{
- std::vector<ExecContext *> &xcvec = cpu->system->execContexts;
- BaseCPU *temp = xcvec[cpu_id]->getCpuPtr();
- temp->clear_interrupt(int_num, index);
-}
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(IntrControl)
-
- SimObjectParam<BaseCPU *> cpu;
-
-END_DECLARE_SIM_OBJECT_PARAMS(IntrControl)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(IntrControl)
-
- INIT_PARAM(cpu, "the cpu")
-
-END_INIT_SIM_OBJECT_PARAMS(IntrControl)
-
-CREATE_SIM_OBJECT(IntrControl)
-{
- return new IntrControl(getInstanceName(), cpu);
-}
-
-REGISTER_SIM_OBJECT("IntrControl", IntrControl)
diff --git a/cpu/intr_control.hh b/cpu/intr_control.hh
deleted file mode 100644
index 5ec4e14cb..000000000
--- a/cpu/intr_control.hh
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __INTR_CONTROL_HH__
-#define __INTR_CONTROL_HH__
-
-#include <vector>
-#include "base/misc.hh"
-#include "cpu/base.hh"
-#include "sim/sim_object.hh"
-#include "sim/system.hh"
-
-
-class IntrControl : public SimObject
-{
- public:
- BaseCPU *cpu;
- IntrControl(const std::string &name, BaseCPU *c);
-
- void clear(int int_num, int index = 0);
- void post(int int_num, int index = 0);
- void clear(int cpu_id, int int_num, int index);
- void post(int cpu_id, int int_num, int index);
-};
-
-#endif // __INTR_CONTROL_HH__
-
-
-
-
-
-
-
diff --git a/cpu/memtest/memtest.cc b/cpu/memtest/memtest.cc
deleted file mode 100644
index 94b66b70b..000000000
--- a/cpu/memtest/memtest.cc
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-// FIX ME: make trackBlkAddr use blocksize from actual cache, not hard coded
-
-#include <iomanip>
-#include <set>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "base/misc.hh"
-#include "base/statistics.hh"
-#include "cpu/cpu_exec_context.hh"
-#include "cpu/memtest/memtest.hh"
-#include "mem/cache/base_cache.hh"
-#include "sim/builder.hh"
-#include "sim/sim_events.hh"
-#include "sim/stats.hh"
-
-using namespace std;
-using namespace TheISA;
-
-int TESTER_ALLOCATOR=0;
-
-MemTest::MemTest(const string &name,
- MemInterface *_cache_interface,
- FunctionalMemory *main_mem,
- FunctionalMemory *check_mem,
- unsigned _memorySize,
- unsigned _percentReads,
- unsigned _percentCopies,
- unsigned _percentUncacheable,
- unsigned _progressInterval,
- unsigned _percentSourceUnaligned,
- unsigned _percentDestUnaligned,
- Addr _traceAddr,
- Counter _max_loads)
- : SimObject(name),
- tickEvent(this),
- cacheInterface(_cache_interface),
- mainMem(main_mem),
- checkMem(check_mem),
- size(_memorySize),
- percentReads(_percentReads),
- percentCopies(_percentCopies),
- percentUncacheable(_percentUncacheable),
- progressInterval(_progressInterval),
- nextProgressMessage(_progressInterval),
- percentSourceUnaligned(_percentSourceUnaligned),
- percentDestUnaligned(percentDestUnaligned),
- maxLoads(_max_loads)
-{
- vector<string> cmd;
- cmd.push_back("/bin/ls");
- vector<string> null_vec;
- cpuXC = new CPUExecContext(NULL, 0, mainMem, 0);
-
- blockSize = cacheInterface->getBlockSize();
- blockAddrMask = blockSize - 1;
- traceBlockAddr = blockAddr(_traceAddr);
-
- //setup data storage with interesting values
- uint8_t *data1 = new uint8_t[size];
- uint8_t *data2 = new uint8_t[size];
- uint8_t *data3 = new uint8_t[size];
- memset(data1, 1, size);
- memset(data2, 2, size);
- memset(data3, 3, size);
- curTick = 0;
-
- baseAddr1 = 0x100000;
- baseAddr2 = 0x400000;
- uncacheAddr = 0x800000;
-
- // set up intial memory contents here
- mainMem->prot_write(baseAddr1, data1, size);
- checkMem->prot_write(baseAddr1, data1, size);
- mainMem->prot_write(baseAddr2, data2, size);
- checkMem->prot_write(baseAddr2, data2, size);
- mainMem->prot_write(uncacheAddr, data3, size);
- checkMem->prot_write(uncacheAddr, data3, size);
-
- delete [] data1;
- delete [] data2;
- delete [] data3;
-
- // set up counters
- noResponseCycles = 0;
- numReads = 0;
- tickEvent.schedule(0);
-
- id = TESTER_ALLOCATOR++;
-}
-
-static void
-printData(ostream &os, uint8_t *data, int nbytes)
-{
- os << hex << setfill('0');
- // assume little-endian: print bytes from highest address to lowest
- for (uint8_t *dp = data + nbytes - 1; dp >= data; --dp) {
- os << setw(2) << (unsigned)*dp;
- }
- os << dec;
-}
-
-void
-MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
-{
- //Remove the address from the list of outstanding
- std::set<unsigned>::iterator removeAddr = outstandingAddrs.find(req->paddr);
- assert(removeAddr != outstandingAddrs.end());
- outstandingAddrs.erase(removeAddr);
-
- switch (req->cmd) {
- case Read:
- if (memcmp(req->data, data, req->size) != 0) {
- cerr << name() << ": on read of 0x" << hex << req->paddr
- << " (0x" << hex << blockAddr(req->paddr) << ")"
- << "@ cycle " << dec << curTick
- << ", cache returns 0x";
- printData(cerr, req->data, req->size);
- cerr << ", expected 0x";
- printData(cerr, data, req->size);
- cerr << endl;
- fatal("");
- }
-
- numReads++;
- numReadsStat++;
-
- if (numReads == nextProgressMessage) {
- ccprintf(cerr, "%s: completed %d read accesses @%d\n",
- name(), numReads, curTick);
- nextProgressMessage += progressInterval;
- }
-
- if (numReads >= maxLoads)
- SimExit(curTick, "Maximum number of loads reached!");
- break;
-
- case Write:
- numWritesStat++;
- break;
-
- case Copy:
- //Also remove dest from outstanding list
- removeAddr = outstandingAddrs.find(req->dest);
- assert(removeAddr != outstandingAddrs.end());
- outstandingAddrs.erase(removeAddr);
- numCopiesStat++;
- break;
-
- default:
- panic("invalid command");
- }
-
- if (blockAddr(req->paddr) == traceBlockAddr) {
- cerr << name() << ": completed "
- << (req->cmd.isWrite() ? "write" : "read")
- << " access of "
- << dec << req->size << " bytes at address 0x"
- << hex << req->paddr
- << " (0x" << hex << blockAddr(req->paddr) << ")"
- << ", value = 0x";
- printData(cerr, req->data, req->size);
- cerr << " @ cycle " << dec << curTick;
-
- cerr << endl;
- }
-
- noResponseCycles = 0;
- delete [] data;
-}
-
-
-void
-MemTest::regStats()
-{
- using namespace Stats;
-
-
- numReadsStat
- .name(name() + ".num_reads")
- .desc("number of read accesses completed")
- ;
-
- numWritesStat
- .name(name() + ".num_writes")
- .desc("number of write accesses completed")
- ;
-
- numCopiesStat
- .name(name() + ".num_copies")
- .desc("number of copy accesses completed")
- ;
-}
-
-void
-MemTest::tick()
-{
- if (!tickEvent.scheduled())
- tickEvent.schedule(curTick + cycles(1));
-
- if (++noResponseCycles >= 500000) {
- cerr << name() << ": deadlocked at cycle " << curTick << endl;
- fatal("");
- }
-
- if (cacheInterface->isBlocked()) {
- return;
- }
-
- //make new request
- unsigned cmd = random() % 100;
- unsigned offset = random() % size;
- unsigned base = random() % 2;
- uint64_t data = random();
- unsigned access_size = random() % 4;
- unsigned cacheable = random() % 100;
-
- //If we aren't doing copies, use id as offset, and do a false sharing
- //mem tester
- if (percentCopies == 0) {
- //We can eliminate the lower bits of the offset, and then use the id
- //to offset within the blks
- offset &= ~63; //Not the low order bits
- offset += id;
- access_size = 0;
- }
-
- MemReqPtr req = new MemReq();
-
- if (cacheable < percentUncacheable) {
- req->flags |= UNCACHEABLE;
- req->paddr = uncacheAddr + offset;
- } else {
- req->paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
- }
- // bool probe = (random() % 2 == 1) && !req->isUncacheable();
- bool probe = false;
-
- req->size = 1 << access_size;
- req->data = new uint8_t[req->size];
- req->paddr &= ~(req->size - 1);
- req->time = curTick;
- req->xc = cpuXC->getProxy();
-
- if (cmd < percentReads) {
- // read
-
- //For now we only allow one outstanding request per addreess per tester
- //This means we assume CPU does write forwarding to reads that alias something
- //in the cpu store buffer.
- if (outstandingAddrs.find(req->paddr) != outstandingAddrs.end()) return;
- else outstandingAddrs.insert(req->paddr);
-
- req->cmd = Read;
- uint8_t *result = new uint8_t[8];
- checkMem->access(Read, req->paddr, result, req->size);
- if (blockAddr(req->paddr) == traceBlockAddr) {
- cerr << name()
- << ": initiating read "
- << ((probe) ? "probe of " : "access of ")
- << dec << req->size << " bytes from addr 0x"
- << hex << req->paddr
- << " (0x" << hex << blockAddr(req->paddr) << ")"
- << " at cycle "
- << dec << curTick << endl;
- }
- if (probe) {
- cacheInterface->probeAndUpdate(req);
- completeRequest(req, result);
- } else {
- req->completionEvent = new MemCompleteEvent(req, result, this);
- cacheInterface->access(req);
- }
- } else if (cmd < (100 - percentCopies)){
- // write
-
- //For now we only allow one outstanding request per addreess per tester
- //This means we assume CPU does write forwarding to reads that alias something
- //in the cpu store buffer.
- if (outstandingAddrs.find(req->paddr) != outstandingAddrs.end()) return;
- else outstandingAddrs.insert(req->paddr);
-
- req->cmd = Write;
- memcpy(req->data, &data, req->size);
- checkMem->access(Write, req->paddr, req->data, req->size);
- if (blockAddr(req->paddr) == traceBlockAddr) {
- cerr << name() << ": initiating write "
- << ((probe)?"probe of ":"access of ")
- << dec << req->size << " bytes (value = 0x";
- printData(cerr, req->data, req->size);
- cerr << ") to addr 0x"
- << hex << req->paddr
- << " (0x" << hex << blockAddr(req->paddr) << ")"
- << " at cycle "
- << dec << curTick << endl;
- }
- if (probe) {
- cacheInterface->probeAndUpdate(req);
- completeRequest(req, NULL);
- } else {
- req->completionEvent = new MemCompleteEvent(req, NULL, this);
- cacheInterface->access(req);
- }
- } else {
- // copy
- unsigned source_align = random() % 100;
- unsigned dest_align = random() % 100;
- unsigned offset2 = random() % size;
-
- Addr source = ((base) ? baseAddr1 : baseAddr2) + offset;
- Addr dest = ((base) ? baseAddr2 : baseAddr1) + offset2;
- if (outstandingAddrs.find(source) != outstandingAddrs.end()) return;
- else outstandingAddrs.insert(source);
- if (outstandingAddrs.find(dest) != outstandingAddrs.end()) return;
- else outstandingAddrs.insert(dest);
-
- if (source_align >= percentSourceUnaligned) {
- source = blockAddr(source);
- }
- if (dest_align >= percentDestUnaligned) {
- dest = blockAddr(dest);
- }
- req->cmd = Copy;
- req->flags &= ~UNCACHEABLE;
- req->paddr = source;
- req->dest = dest;
- delete [] req->data;
- req->data = new uint8_t[blockSize];
- req->size = blockSize;
- if (source == traceBlockAddr || dest == traceBlockAddr) {
- cerr << name()
- << ": initiating copy of "
- << dec << req->size << " bytes from addr 0x"
- << hex << source
- << " (0x" << hex << blockAddr(source) << ")"
- << " to addr 0x"
- << hex << dest
- << " (0x" << hex << blockAddr(dest) << ")"
- << " at cycle "
- << dec << curTick << endl;
- }
- cacheInterface->access(req);
- uint8_t result[blockSize];
- checkMem->access(Read, source, &result, blockSize);
- checkMem->access(Write, dest, &result, blockSize);
- }
-}
-
-
-void
-MemCompleteEvent::process()
-{
- tester->completeRequest(req, data);
- delete this;
-}
-
-
-const char *
-MemCompleteEvent::description()
-{
- return "memory access completion";
-}
-
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(MemTest)
-
- SimObjectParam<BaseCache *> cache;
- SimObjectParam<FunctionalMemory *> main_mem;
- SimObjectParam<FunctionalMemory *> check_mem;
- Param<unsigned> memory_size;
- Param<unsigned> percent_reads;
- Param<unsigned> percent_copies;
- Param<unsigned> percent_uncacheable;
- Param<unsigned> progress_interval;
- Param<unsigned> percent_source_unaligned;
- Param<unsigned> percent_dest_unaligned;
- Param<Addr> trace_addr;
- Param<Counter> max_loads;
-
-END_DECLARE_SIM_OBJECT_PARAMS(MemTest)
-
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(MemTest)
-
- INIT_PARAM(cache, "L1 cache"),
- INIT_PARAM(main_mem, "hierarchical memory"),
- INIT_PARAM(check_mem, "check memory"),
- INIT_PARAM(memory_size, "memory size"),
- INIT_PARAM(percent_reads, "target read percentage"),
- INIT_PARAM(percent_copies, "target copy percentage"),
- INIT_PARAM(percent_uncacheable, "target uncacheable percentage"),
- INIT_PARAM(progress_interval, "progress report interval (in accesses)"),
- INIT_PARAM(percent_source_unaligned,
- "percent of copy source address that are unaligned"),
- INIT_PARAM(percent_dest_unaligned,
- "percent of copy dest address that are unaligned"),
- INIT_PARAM(trace_addr, "address to trace"),
- INIT_PARAM(max_loads, "terminate when we have reached this load count")
-
-END_INIT_SIM_OBJECT_PARAMS(MemTest)
-
-
-CREATE_SIM_OBJECT(MemTest)
-{
- return new MemTest(getInstanceName(), cache->getInterface(), main_mem,
- check_mem, memory_size, percent_reads, percent_copies,
- percent_uncacheable, progress_interval,
- percent_source_unaligned, percent_dest_unaligned,
- trace_addr, max_loads);
-}
-
-REGISTER_SIM_OBJECT("MemTest", MemTest)
diff --git a/cpu/memtest/memtest.hh b/cpu/memtest/memtest.hh
deleted file mode 100644
index cdb40a26a..000000000
--- a/cpu/memtest/memtest.hh
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_MEMTEST_MEMTEST_HH__
-#define __CPU_MEMTEST_MEMTEST_HH__
-
-#include <set>
-
-#include "base/statistics.hh"
-#include "mem/functional/functional.hh"
-#include "mem/mem_interface.hh"
-#include "sim/eventq.hh"
-#include "sim/sim_exit.hh"
-#include "sim/sim_object.hh"
-#include "sim/stats.hh"
-
-class ExecContext;
-class MemTest : public SimObject
-{
- public:
-
- MemTest(const std::string &name,
- MemInterface *_cache_interface,
- FunctionalMemory *main_mem,
- FunctionalMemory *check_mem,
- unsigned _memorySize,
- unsigned _percentReads,
- unsigned _percentCopies,
- unsigned _percentUncacheable,
- unsigned _progressInterval,
- unsigned _percentSourceUnaligned,
- unsigned _percentDestUnaligned,
- Addr _traceAddr,
- Counter _max_loads);
-
- // register statistics
- virtual void regStats();
-
- inline Tick cycles(int numCycles) const { return numCycles; }
-
- // main simulation loop (one cycle)
- void tick();
-
- protected:
- class TickEvent : public Event
- {
- private:
- MemTest *cpu;
- public:
- TickEvent(MemTest *c)
- : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c) {}
- void process() {cpu->tick();}
- virtual const char *description() { return "tick event"; }
- };
-
- TickEvent tickEvent;
-
- MemInterface *cacheInterface;
- FunctionalMemory *mainMem;
- FunctionalMemory *checkMem;
- CPUExecContext *cpuXC;
-
- unsigned size; // size of testing memory region
-
- unsigned percentReads; // target percentage of read accesses
- unsigned percentCopies; // target percentage of copy accesses
- unsigned percentUncacheable;
-
- int id;
-
- std::set<unsigned> outstandingAddrs;
-
- unsigned blockSize;
-
- Addr blockAddrMask;
-
- Addr blockAddr(Addr addr)
- {
- return (addr & ~blockAddrMask);
- }
-
- Addr traceBlockAddr;
-
- Addr baseAddr1; // fix this to option
- Addr baseAddr2; // fix this to option
- Addr uncacheAddr;
-
- unsigned progressInterval; // frequency of progress reports
- Tick nextProgressMessage; // access # for next progress report
-
- unsigned percentSourceUnaligned;
- unsigned percentDestUnaligned;
-
- Tick noResponseCycles;
-
- uint64_t numReads;
- uint64_t maxLoads;
- Stats::Scalar<> numReadsStat;
- Stats::Scalar<> numWritesStat;
- Stats::Scalar<> numCopiesStat;
-
- // called by MemCompleteEvent::process()
- void completeRequest(MemReqPtr &req, uint8_t *data);
-
- friend class MemCompleteEvent;
-};
-
-
-class MemCompleteEvent : public Event
-{
- MemReqPtr req;
- uint8_t *data;
- MemTest *tester;
-
- public:
-
- MemCompleteEvent(MemReqPtr &_req, uint8_t *_data, MemTest *_tester)
- : Event(&mainEventQueue),
- req(_req), data(_data), tester(_tester)
- {
- }
-
- void process();
-
- virtual const char *description();
-};
-
-#endif // __CPU_MEMTEST_MEMTEST_HH__
-
-
-
diff --git a/cpu/o3/2bit_local_pred.cc b/cpu/o3/2bit_local_pred.cc
deleted file mode 100644
index 33c417c88..000000000
--- a/cpu/o3/2bit_local_pred.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "base/intmath.hh"
-#include "base/trace.hh"
-#include "cpu/o3/2bit_local_pred.hh"
-
-LocalBP::LocalBP(unsigned _localPredictorSize,
- unsigned _localCtrBits,
- unsigned _instShiftAmt)
- : localPredictorSize(_localPredictorSize),
- localCtrBits(_localCtrBits),
- instShiftAmt(_instShiftAmt)
-{
- if (!isPowerOf2(localPredictorSize)) {
- fatal("Invalid local predictor size!\n");
- }
-
- localPredictorSets = localPredictorSize / localCtrBits;
-
- if (!isPowerOf2(localPredictorSets)) {
- fatal("Invalid number of local predictor sets! Check localCtrBits.\n");
- }
-
- // Setup the index mask.
- indexMask = localPredictorSets - 1;
-
- DPRINTF(Fetch, "Branch predictor: index mask: %#x\n", indexMask);
-
- // Setup the array of counters for the local predictor.
- localCtrs.resize(localPredictorSets);
-
- for (int i = 0; i < localPredictorSets; ++i)
- localCtrs[i].setBits(_localCtrBits);
-
- DPRINTF(Fetch, "Branch predictor: local predictor size: %i\n",
- localPredictorSize);
-
- DPRINTF(Fetch, "Branch predictor: local counter bits: %i\n", localCtrBits);
-
- DPRINTF(Fetch, "Branch predictor: instruction shift amount: %i\n",
- instShiftAmt);
-}
-
-void
-LocalBP::reset()
-{
- for (int i = 0; i < localPredictorSets; ++i) {
- localCtrs[i].reset();
- }
-}
-
-bool
-LocalBP::lookup(Addr &branch_addr, void * &bp_history)
-{
- bool taken;
- uint8_t counter_val;
- unsigned local_predictor_idx = getLocalIndex(branch_addr);
-
- DPRINTF(Fetch, "Branch predictor: Looking up index %#x\n",
- local_predictor_idx);
-
- counter_val = localCtrs[local_predictor_idx].read();
-
- DPRINTF(Fetch, "Branch predictor: prediction is %i.\n",
- (int)counter_val);
-
- taken = getPrediction(counter_val);
-
-#if 0
- // Speculative update.
- if (taken) {
- DPRINTF(Fetch, "Branch predictor: Branch updated as taken.\n");
- localCtrs[local_predictor_idx].increment();
- } else {
- DPRINTF(Fetch, "Branch predictor: Branch updated as not taken.\n");
- localCtrs[local_predictor_idx].decrement();
- }
-#endif
-
- return taken;
-}
-
-void
-LocalBP::update(Addr &branch_addr, bool taken, void *bp_history)
-{
- assert(bp_history == NULL);
- unsigned local_predictor_idx;
-
- // Update the local predictor.
- local_predictor_idx = getLocalIndex(branch_addr);
-
- DPRINTF(Fetch, "Branch predictor: Looking up index %#x\n",
- local_predictor_idx);
-
- if (taken) {
- DPRINTF(Fetch, "Branch predictor: Branch updated as taken.\n");
- localCtrs[local_predictor_idx].increment();
- } else {
- DPRINTF(Fetch, "Branch predictor: Branch updated as not taken.\n");
- localCtrs[local_predictor_idx].decrement();
- }
-}
-
-inline
-bool
-LocalBP::getPrediction(uint8_t &count)
-{
- // Get the MSB of the count
- return (count >> (localCtrBits - 1));
-}
-
-inline
-unsigned
-LocalBP::getLocalIndex(Addr &branch_addr)
-{
- return (branch_addr >> instShiftAmt) & indexMask;
-}
diff --git a/cpu/o3/2bit_local_pred.hh b/cpu/o3/2bit_local_pred.hh
deleted file mode 100644
index 02595702b..000000000
--- a/cpu/o3/2bit_local_pred.hh
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_2BIT_LOCAL_PRED_HH__
-#define __CPU_O3_2BIT_LOCAL_PRED_HH__
-
-// For Addr type.
-#include "arch/isa_traits.hh"
-#include "cpu/o3/sat_counter.hh"
-
-#include <vector>
-
-/**
- * Implements a local predictor that uses the PC to index into a table of
- * counters. Note that any time a pointer to the bp_history is given, it
- * should be NULL using this predictor because it does not have any branch
- * predictor state that needs to be recorded or updated; the update can be
- * determined solely by the branch being taken or not taken.
- */
-class LocalBP
-{
- public:
- /**
- * Default branch predictor constructor.
- * @param localPredictorSize Size of the local predictor.
- * @param localCtrBits Number of bits per counter.
- * @param instShiftAmt Offset amount for instructions to ignore alignment.
- */
- LocalBP(unsigned localPredictorSize, unsigned localCtrBits,
- unsigned instShiftAmt);
-
- /**
- * Looks up the given address in the branch predictor and returns
- * a true/false value as to whether it is taken.
- * @param branch_addr The address of the branch to look up.
- * @param bp_history Pointer to any bp history state.
- * @return Whether or not the branch is taken.
- */
- bool lookup(Addr &branch_addr, void * &bp_history);
-
- /**
- * Updates the branch predictor with the actual result of a branch.
- * @param branch_addr The address of the branch to update.
- * @param taken Whether or not the branch was taken.
- */
- void update(Addr &branch_addr, bool taken, void *bp_history);
-
- void squash(void *bp_history)
- { assert(bp_history == NULL); }
-
- void reset();
-
- private:
- /**
- * Returns the taken/not taken prediction given the value of the
- * counter.
- * @param count The value of the counter.
- * @return The prediction based on the counter value.
- */
- inline bool getPrediction(uint8_t &count);
-
- /** Calculates the local index based on the PC. */
- inline unsigned getLocalIndex(Addr &PC);
-
- /** Array of counters that make up the local predictor. */
- std::vector<SatCounter> localCtrs;
-
- /** Size of the local predictor. */
- unsigned localPredictorSize;
-
- /** Number of sets. */
- unsigned localPredictorSets;
-
- /** Number of bits of the local predictor's counters. */
- unsigned localCtrBits;
-
- /** Number of bits to shift the PC when calculating index. */
- unsigned instShiftAmt;
-
- /** Mask to get index bits. */
- unsigned indexMask;
-};
-
-#endif // __CPU_O3_2BIT_LOCAL_PRED_HH__
diff --git a/cpu/o3/alpha_cpu.cc b/cpu/o3/alpha_cpu.cc
deleted file mode 100644
index 7bc90dae6..000000000
--- a/cpu/o3/alpha_cpu.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/o3/alpha_impl.hh"
-#include "cpu/o3/alpha_cpu_impl.hh"
-#include "cpu/o3/alpha_dyn_inst.hh"
-
-// Force instantiation of AlphaFullCPU for all the implemntations that are
-// needed. Consider merging this and alpha_dyn_inst.cc, and maybe all
-// classes that depend on a certain impl, into one file (alpha_impl.cc?).
-template class AlphaFullCPU<AlphaSimpleImpl>;
diff --git a/cpu/o3/alpha_cpu.hh b/cpu/o3/alpha_cpu.hh
deleted file mode 100644
index 4c452c4dd..000000000
--- a/cpu/o3/alpha_cpu.hh
+++ /dev/null
@@ -1,518 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_ALPHA_FULL_CPU_HH__
-#define __CPU_O3_ALPHA_FULL_CPU_HH__
-
-#include "arch/isa_traits.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/o3/cpu.hh"
-#include "sim/byteswap.hh"
-
-class EndQuiesceEvent;
-namespace Kernel {
- class Statistics;
-};
-
-/**
- * AlphaFullCPU class. Derives from the FullO3CPU class, and
- * implements all ISA and implementation specific functions of the
- * CPU. This is the CPU class that is used for the SimObjects, and is
- * what is given to the DynInsts. Most of its state exists in the
- * FullO3CPU; the state is has is mainly for ISA specific
- * functionality.
- */
-template <class Impl>
-class AlphaFullCPU : public FullO3CPU<Impl>
-{
- protected:
- typedef TheISA::IntReg IntReg;
- typedef TheISA::MiscReg MiscReg;
- typedef TheISA::RegFile RegFile;
- typedef TheISA::MiscRegFile MiscRegFile;
-
- public:
- typedef O3ThreadState<Impl> ImplState;
- typedef O3ThreadState<Impl> Thread;
- typedef typename Impl::Params Params;
-
- /** Constructs an AlphaFullCPU with the given parameters. */
- AlphaFullCPU(Params *params);
-
- /**
- * Derived ExecContext class for use with the AlphaFullCPU. It
- * provides the interface for any external objects to access a
- * single thread's state and some general CPU state. Any time
- * external objects try to update state through this interface,
- * the CPU will create an event to squash all in-flight
- * instructions in order to ensure state is maintained correctly.
- */
- class AlphaXC : public ExecContext
- {
- public:
- /** Pointer to the CPU. */
- AlphaFullCPU<Impl> *cpu;
-
- /** Pointer to the thread state that this XC corrseponds to. */
- O3ThreadState<Impl> *thread;
-
- /** Returns a pointer to this CPU. */
- virtual BaseCPU *getCpuPtr() { return cpu; }
-
- /** Sets this CPU's ID. */
- virtual void setCpuId(int id) { cpu->cpu_id = id; }
-
- /** Reads this CPU's ID. */
- virtual int readCpuId() { return cpu->cpu_id; }
-
- /** Returns a pointer to functional memory. */
- virtual FunctionalMemory *getMemPtr() { return thread->mem; }
-
-#if FULL_SYSTEM
- /** Returns a pointer to the system. */
- virtual System *getSystemPtr() { return cpu->system; }
-
- /** Returns a pointer to physical memory. */
- virtual PhysicalMemory *getPhysMemPtr() { return cpu->physmem; }
-
- /** Returns a pointer to the ITB. */
- virtual AlphaITB *getITBPtr() { return cpu->itb; }
-
- /** Returns a pointer to the DTB. */
- virtual AlphaDTB *getDTBPtr() { return cpu->dtb; }
-
- /** Returns a pointer to this thread's kernel statistics. */
- virtual Kernel::Statistics *getKernelStats()
- { return thread->kernelStats; }
-#else
- /** Returns a pointer to this thread's process. */
- virtual Process *getProcessPtr() { return thread->process; }
-#endif
- /** Returns this thread's status. */
- virtual Status status() const { return thread->status(); }
-
- /** Sets this thread's status. */
- virtual void setStatus(Status new_status)
- { thread->setStatus(new_status); }
-
- /** Set the status to Active. Optional delay indicates number of
- * cycles to wait before beginning execution. */
- virtual void activate(int delay = 1);
-
- /** Set the status to Suspended. */
- virtual void suspend();
-
- /** Set the status to Unallocated. */
- virtual void deallocate();
-
- /** Set the status to Halted. */
- virtual void halt();
-
-#if FULL_SYSTEM
- /** Dumps the function profiling information.
- * @todo: Implement.
- */
- virtual void dumpFuncProfile();
-#endif
- /** Takes over execution of a thread from another CPU. */
- virtual void takeOverFrom(ExecContext *old_context);
-
- /** Registers statistics associated with this XC. */
- virtual void regStats(const std::string &name);
-
- /** Serializes state. */
- virtual void serialize(std::ostream &os);
- /** Unserializes state. */
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-
-#if FULL_SYSTEM
- /** Returns pointer to the quiesce event. */
- virtual EndQuiesceEvent *getQuiesceEvent();
-
- /** Reads the last tick that this thread was activated on. */
- virtual Tick readLastActivate();
- /** Reads the last tick that this thread was suspended on. */
- virtual Tick readLastSuspend();
-
- /** Clears the function profiling information. */
- virtual void profileClear();
- /** Samples the function profiling information. */
- virtual void profileSample();
-#endif
- /** Returns this thread's ID number. */
- virtual int getThreadNum() { return thread->tid; }
-
- /** Returns the instruction this thread is currently committing.
- * Only used when an instruction faults.
- */
- virtual TheISA::MachInst getInst();
-
- /** Copies the architectural registers from another XC into this XC. */
- virtual void copyArchRegs(ExecContext *xc);
-
- /** Resets all architectural registers to 0. */
- virtual void clearArchRegs();
-
- /** Reads an integer register. */
- virtual uint64_t readIntReg(int reg_idx);
-
- /** Reads a single precision floating point register. */
- virtual float readFloatRegSingle(int reg_idx);
-
- /** Reads a double precision floating point register. */
- virtual double readFloatRegDouble(int reg_idx);
-
- /** Reads a floating point register as an integer value. */
- virtual uint64_t readFloatRegInt(int reg_idx);
-
- /** Sets an integer register to a value. */
- virtual void setIntReg(int reg_idx, uint64_t val);
-
- /** Sets a single precision fp register to a value. */
- virtual void setFloatRegSingle(int reg_idx, float val);
-
- /** Sets a double precision fp register to a value. */
- virtual void setFloatRegDouble(int reg_idx, double val);
-
- /** Sets a fp register to an integer value. */
- virtual void setFloatRegInt(int reg_idx, uint64_t val);
-
- /** Reads this thread's PC. */
- virtual uint64_t readPC()
- { return cpu->readPC(thread->tid); }
-
- /** Sets this thread's PC. */
- virtual void setPC(uint64_t val);
-
- /** Reads this thread's next PC. */
- virtual uint64_t readNextPC()
- { return cpu->readNextPC(thread->tid); }
-
- /** Sets this thread's next PC. */
- virtual void setNextPC(uint64_t val);
-
- /** Reads a miscellaneous register. */
- virtual MiscReg readMiscReg(int misc_reg)
- { return cpu->readMiscReg(misc_reg, thread->tid); }
-
- /** Reads a misc. register, including any side-effects the
- * read might have as defined by the architecture. */
- virtual MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
- { return cpu->readMiscRegWithEffect(misc_reg, fault, thread->tid); }
-
- /** Sets a misc. register. */
- virtual Fault setMiscReg(int misc_reg, const MiscReg &val);
-
- /** Sets a misc. register, including any side-effects the
- * write might have as defined by the architecture. */
- virtual Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val);
-
- /** Returns the number of consecutive store conditional failures. */
- // @todo: Figure out where these store cond failures should go.
- virtual unsigned readStCondFailures()
- { return thread->storeCondFailures; }
-
- /** Sets the number of consecutive store conditional failures. */
- virtual void setStCondFailures(unsigned sc_failures)
- { thread->storeCondFailures = sc_failures; }
-
-#if FULL_SYSTEM
- /** Returns if the thread is currently in PAL mode, based on
- * the PC's value. */
- virtual bool inPalMode()
- { return TheISA::PcPAL(cpu->readPC(thread->tid)); }
-#endif
- // Only really makes sense for old CPU model. Lots of code
- // outside the CPU still checks this function, so it will
- // always return false to keep everything working.
- /** Checks if the thread is misspeculating. Because it is
- * very difficult to determine if the thread is
- * misspeculating, this is set as false. */
- virtual bool misspeculating() { return false; }
-
-#if !FULL_SYSTEM
- /** Gets a syscall argument by index. */
- virtual IntReg getSyscallArg(int i);
-
- /** Sets a syscall argument. */
- virtual void setSyscallArg(int i, IntReg val);
-
- /** Sets the syscall return value. */
- virtual void setSyscallReturn(SyscallReturn return_value);
-
- /** Executes a syscall in SE mode. */
- virtual void syscall() { return cpu->syscall(thread->tid); }
-
- /** Reads the funcExeInst counter. */
- virtual Counter readFuncExeInst() { return thread->funcExeInst; }
-#endif
- };
-
-#if FULL_SYSTEM
- /** ITB pointer. */
- AlphaITB *itb;
- /** DTB pointer. */
- AlphaDTB *dtb;
-#endif
-
- /** Registers statistics. */
- void regStats();
-
-#if FULL_SYSTEM
- /** Translates instruction requestion. */
- Fault translateInstReq(MemReqPtr &req)
- {
- return itb->translate(req);
- }
-
- /** Translates data read request. */
- Fault translateDataReadReq(MemReqPtr &req)
- {
- return dtb->translate(req, false);
- }
-
- /** Translates data write request. */
- Fault translateDataWriteReq(MemReqPtr &req)
- {
- return dtb->translate(req, true);
- }
-
-#else
- Fault dummyTranslation(MemReqPtr &req)
- {
-#if 0
- assert((req->vaddr >> 48 & 0xffff) == 0);
-#endif
-
- // put the asid in the upper 16 bits of the paddr
- req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
- req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
- return NoFault;
- }
-
- /** Translates instruction requestion in syscall emulation mode. */
- Fault translateInstReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
-
- /** Translates data read request in syscall emulation mode. */
- Fault translateDataReadReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
-
- /** Translates data write request in syscall emulation mode. */
- Fault translateDataWriteReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
-
-#endif
- /** Reads a miscellaneous register. */
- MiscReg readMiscReg(int misc_reg, unsigned tid);
-
- /** Reads a misc. register, including any side effects the read
- * might have as defined by the architecture.
- */
- MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault, unsigned tid);
-
- /** Sets a miscellaneous register. */
- Fault setMiscReg(int misc_reg, const MiscReg &val, unsigned tid);
-
- /** Sets a misc. register, including any side effects the write
- * might have as defined by the architecture.
- */
- Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val, unsigned tid);
-
- /** Initiates a squash of all in-flight instructions for a given
- * thread. The source of the squash is an external update of
- * state through the XC.
- */
- void squashFromXC(unsigned tid);
-
-#if FULL_SYSTEM
- /** Posts an interrupt. */
- void post_interrupt(int int_num, int index);
- /** Reads the interrupt flag. */
- int readIntrFlag();
- /** Sets the interrupt flags. */
- void setIntrFlag(int val);
- /** HW return from error interrupt. */
- Fault hwrei(unsigned tid);
- /** Returns if a specific PC is a PAL mode PC. */
- bool inPalMode(uint64_t PC)
- { return AlphaISA::PcPAL(PC); }
-
- /** Traps to handle given fault. */
- void trap(Fault fault, unsigned tid);
- bool simPalCheck(int palFunc, unsigned tid);
-
- /** Processes any interrupts. */
- void processInterrupts();
-
- /** Halts the CPU. */
- void halt() { panic("Halt not implemented!\n"); }
-#endif
-
-
-#if !FULL_SYSTEM
- /** Executes a syscall.
- * @todo: Determine if this needs to be virtual.
- */
- void syscall(int tid);
- /** Gets a syscall argument. */
- IntReg getSyscallArg(int i, int tid);
-
- /** Used to shift args for indirect syscall. */
- void setSyscallArg(int i, IntReg val, int tid);
-
- /** Sets the return value of a syscall. */
- void setSyscallReturn(SyscallReturn return_value, int tid);
-#endif
-
- /** Read from memory function. */
- template <class T>
- Fault read(MemReqPtr &req, T &data)
- {
-#if 0
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
- if (req->flags & LOCKED) {
- req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
- req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
- }
-#endif
-#endif
- Fault error;
-
-#if FULL_SYSTEM
- // @todo: Fix this LL/SC hack.
- if (req->flags & LOCKED) {
- lockAddr = req->paddr;
- lockFlag = true;
- }
-#endif
-
- error = this->mem->read(req, data);
- data = gtoh(data);
- return error;
- }
-
- /** CPU read function, forwards read to LSQ. */
- template <class T>
- Fault read(MemReqPtr &req, T &data, int load_idx)
- {
- return this->iew.ldstQueue.read(req, data, load_idx);
- }
-
- /** Write to memory function. */
- template <class T>
- Fault write(MemReqPtr &req, T &data)
- {
-#if 0
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
- ExecContext *xc;
-
- // If this is a store conditional, act appropriately
- if (req->flags & LOCKED) {
- xc = req->xc;
-
- if (req->flags & UNCACHEABLE) {
- // Don't update result register (see stq_c in isa_desc)
- req->result = 2;
- xc->setStCondFailures(0);//Needed? [RGD]
- } else {
- bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag);
- Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag);
- req->result = lock_flag;
- if (!lock_flag ||
- ((lock_addr & ~0xf) != (req->paddr & ~0xf))) {
- xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
- xc->setStCondFailures(xc->readStCondFailures() + 1);
- if (((xc->readStCondFailures()) % 100000) == 0) {
- std::cerr << "Warning: "
- << xc->readStCondFailures()
- << " consecutive store conditional failures "
- << "on cpu " << req->xc->readCpuId()
- << std::endl;
- }
- return NoFault;
- }
- else xc->setStCondFailures(0);
- }
- }
-
- // Need to clear any locked flags on other proccessors for
- // this address. Only do this for succsful Store Conditionals
- // and all other stores (WH64?). Unsuccessful Store
- // Conditionals would have returned above, and wouldn't fall
- // through.
- for (int i = 0; i < this->system->execContexts.size(); i++){
- xc = this->system->execContexts[i];
- if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
- (req->paddr & ~0xf)) {
- xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
- }
- }
-
-#endif
-#endif
-
-#if FULL_SYSTEM
- // @todo: Fix this LL/SC hack.
- if (req->flags & LOCKED) {
- if (req->flags & UNCACHEABLE) {
- req->result = 2;
- } else {
- if (this->lockFlag) {
- req->result = 1;
- } else {
- req->result = 0;
- return NoFault;
- }
- }
- }
-#endif
-
- return this->mem->write(req, (T)htog(data));
- }
-
- /** CPU write function, forwards write to LSQ. */
- template <class T>
- Fault write(MemReqPtr &req, T &data, int store_idx)
- {
- return this->iew.ldstQueue.write(req, data, store_idx);
- }
-
- Addr lockAddr;
-
- /** Temporary fix for the lock flag, works in the UP case. */
- bool lockFlag;
-};
-
-#endif // __CPU_O3_ALPHA_FULL_CPU_HH__
diff --git a/cpu/o3/alpha_cpu_builder.cc b/cpu/o3/alpha_cpu_builder.cc
deleted file mode 100644
index 08d42cd46..000000000
--- a/cpu/o3/alpha_cpu_builder.cc
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <string>
-
-#include "cpu/base.hh"
-#include "cpu/o3/alpha_cpu.hh"
-#include "cpu/o3/alpha_impl.hh"
-#include "cpu/o3/alpha_params.hh"
-#include "cpu/o3/fu_pool.hh"
-#include "mem/cache/base_cache.hh"
-#include "sim/builder.hh"
-
-class DerivAlphaFullCPU : public AlphaFullCPU<AlphaSimpleImpl>
-{
- public:
- DerivAlphaFullCPU(AlphaSimpleParams *p)
- : AlphaFullCPU<AlphaSimpleImpl>(p)
- { }
-};
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
-
- Param<int> clock;
- Param<int> numThreads;
-Param<int> activity;
-
-#if FULL_SYSTEM
-SimObjectParam<System *> system;
-Param<int> cpu_id;
-SimObjectParam<AlphaITB *> itb;
-SimObjectParam<AlphaDTB *> dtb;
-#else
-SimObjectVectorParam<Process *> workload;
-//SimObjectParam<PageTable *> page_table;
-#endif // FULL_SYSTEM
-
-SimObjectParam<FunctionalMemory *> mem;
-
-SimObjectParam<BaseCPU *> checker;
-
-Param<Counter> max_insts_any_thread;
-Param<Counter> max_insts_all_threads;
-Param<Counter> max_loads_any_thread;
-Param<Counter> max_loads_all_threads;
-
-SimObjectParam<BaseCache *> icache;
-SimObjectParam<BaseCache *> dcache;
-
-Param<unsigned> cachePorts;
-
-Param<unsigned> decodeToFetchDelay;
-Param<unsigned> renameToFetchDelay;
-Param<unsigned> iewToFetchDelay;
-Param<unsigned> commitToFetchDelay;
-Param<unsigned> fetchWidth;
-
-Param<unsigned> renameToDecodeDelay;
-Param<unsigned> iewToDecodeDelay;
-Param<unsigned> commitToDecodeDelay;
-Param<unsigned> fetchToDecodeDelay;
-Param<unsigned> decodeWidth;
-
-Param<unsigned> iewToRenameDelay;
-Param<unsigned> commitToRenameDelay;
-Param<unsigned> decodeToRenameDelay;
-Param<unsigned> renameWidth;
-
-Param<unsigned> commitToIEWDelay;
-Param<unsigned> renameToIEWDelay;
-Param<unsigned> issueToExecuteDelay;
-Param<unsigned> issueWidth;
-Param<unsigned> executeWidth;
-Param<unsigned> executeIntWidth;
-Param<unsigned> executeFloatWidth;
-Param<unsigned> executeBranchWidth;
-Param<unsigned> executeMemoryWidth;
-SimObjectParam<FUPool *> fuPool;
-
-Param<unsigned> iewToCommitDelay;
-Param<unsigned> renameToROBDelay;
-Param<unsigned> commitWidth;
-Param<unsigned> squashWidth;
-Param<Tick> trapLatency;
-Param<Tick> fetchTrapLatency;
-
-Param<std::string> predType;
-Param<unsigned> localPredictorSize;
-Param<unsigned> localCtrBits;
-Param<unsigned> localHistoryTableSize;
-Param<unsigned> localHistoryBits;
-Param<unsigned> globalPredictorSize;
-Param<unsigned> globalCtrBits;
-Param<unsigned> globalHistoryBits;
-Param<unsigned> choicePredictorSize;
-Param<unsigned> choiceCtrBits;
-
-Param<unsigned> BTBEntries;
-Param<unsigned> BTBTagSize;
-
-Param<unsigned> RASSize;
-
-Param<unsigned> LQEntries;
-Param<unsigned> SQEntries;
-Param<unsigned> LFSTSize;
-Param<unsigned> SSITSize;
-
-Param<unsigned> numPhysIntRegs;
-Param<unsigned> numPhysFloatRegs;
-Param<unsigned> numIQEntries;
-Param<unsigned> numROBEntries;
-
-Param<unsigned> smtNumFetchingThreads;
-Param<std::string> smtFetchPolicy;
-Param<std::string> smtLSQPolicy;
-Param<unsigned> smtLSQThreshold;
-Param<std::string> smtIQPolicy;
-Param<unsigned> smtIQThreshold;
-Param<std::string> smtROBPolicy;
-Param<unsigned> smtROBThreshold;
-Param<std::string> smtCommitPolicy;
-
-Param<unsigned> instShiftAmt;
-
-Param<bool> defer_registration;
-
-Param<bool> function_trace;
-Param<Tick> function_trace_start;
-
-END_DECLARE_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
-
- INIT_PARAM(clock, "clock speed"),
- INIT_PARAM(numThreads, "number of HW thread contexts"),
- INIT_PARAM_DFLT(activity, "Initial activity count", 0),
-
-#if FULL_SYSTEM
- INIT_PARAM(system, "System object"),
- INIT_PARAM(cpu_id, "processor ID"),
- INIT_PARAM(itb, "Instruction translation buffer"),
- INIT_PARAM(dtb, "Data translation buffer"),
-#else
- INIT_PARAM(workload, "Processes to run"),
-// INIT_PARAM(page_table, "Page table"),
-#endif // FULL_SYSTEM
-
- INIT_PARAM_DFLT(mem, "Memory", NULL),
-
- INIT_PARAM_DFLT(checker, "Checker CPU", NULL),
-
- INIT_PARAM_DFLT(max_insts_any_thread,
- "Terminate when any thread reaches this inst count",
- 0),
- INIT_PARAM_DFLT(max_insts_all_threads,
- "Terminate when all threads have reached"
- "this inst count",
- 0),
- INIT_PARAM_DFLT(max_loads_any_thread,
- "Terminate when any thread reaches this load count",
- 0),
- INIT_PARAM_DFLT(max_loads_all_threads,
- "Terminate when all threads have reached this load"
- "count",
- 0),
-
- INIT_PARAM_DFLT(icache, "L1 instruction cache", NULL),
- INIT_PARAM_DFLT(dcache, "L1 data cache", NULL),
-
- INIT_PARAM_DFLT(cachePorts, "Cache Ports", 200),
-
- INIT_PARAM(decodeToFetchDelay, "Decode to fetch delay"),
- INIT_PARAM(renameToFetchDelay, "Rename to fetch delay"),
- INIT_PARAM(iewToFetchDelay, "Issue/Execute/Writeback to fetch"
- "delay"),
- INIT_PARAM(commitToFetchDelay, "Commit to fetch delay"),
- INIT_PARAM(fetchWidth, "Fetch width"),
- INIT_PARAM(renameToDecodeDelay, "Rename to decode delay"),
- INIT_PARAM(iewToDecodeDelay, "Issue/Execute/Writeback to decode"
- "delay"),
- INIT_PARAM(commitToDecodeDelay, "Commit to decode delay"),
- INIT_PARAM(fetchToDecodeDelay, "Fetch to decode delay"),
- INIT_PARAM(decodeWidth, "Decode width"),
-
- INIT_PARAM(iewToRenameDelay, "Issue/Execute/Writeback to rename"
- "delay"),
- INIT_PARAM(commitToRenameDelay, "Commit to rename delay"),
- INIT_PARAM(decodeToRenameDelay, "Decode to rename delay"),
- INIT_PARAM(renameWidth, "Rename width"),
-
- INIT_PARAM(commitToIEWDelay, "Commit to "
- "Issue/Execute/Writeback delay"),
- INIT_PARAM(renameToIEWDelay, "Rename to "
- "Issue/Execute/Writeback delay"),
- INIT_PARAM(issueToExecuteDelay, "Issue to execute delay (internal"
- "to the IEW stage)"),
- INIT_PARAM(issueWidth, "Issue width"),
- INIT_PARAM(executeWidth, "Execute width"),
- INIT_PARAM(executeIntWidth, "Integer execute width"),
- INIT_PARAM(executeFloatWidth, "Floating point execute width"),
- INIT_PARAM(executeBranchWidth, "Branch execute width"),
- INIT_PARAM(executeMemoryWidth, "Memory execute width"),
- INIT_PARAM_DFLT(fuPool, "Functional unit pool", NULL),
-
- INIT_PARAM(iewToCommitDelay, "Issue/Execute/Writeback to commit "
- "delay"),
- INIT_PARAM(renameToROBDelay, "Rename to reorder buffer delay"),
- INIT_PARAM(commitWidth, "Commit width"),
- INIT_PARAM(squashWidth, "Squash width"),
- INIT_PARAM_DFLT(trapLatency, "Number of cycles before the trap is handled", 6),
- INIT_PARAM_DFLT(fetchTrapLatency, "Number of cycles before the fetch trap is handled", 12),
-
- INIT_PARAM(predType, "Type of branch predictor ('local', 'tournament')"),
- INIT_PARAM(localPredictorSize, "Size of local predictor"),
- INIT_PARAM(localCtrBits, "Bits per counter"),
- INIT_PARAM(localHistoryTableSize, "Size of local history table"),
- INIT_PARAM(localHistoryBits, "Bits for the local history"),
- INIT_PARAM(globalPredictorSize, "Size of global predictor"),
- INIT_PARAM(globalCtrBits, "Bits per counter"),
- INIT_PARAM(globalHistoryBits, "Bits of history"),
- INIT_PARAM(choicePredictorSize, "Size of choice predictor"),
- INIT_PARAM(choiceCtrBits, "Bits of choice counters"),
-
- INIT_PARAM(BTBEntries, "Number of BTB entries"),
- INIT_PARAM(BTBTagSize, "Size of the BTB tags, in bits"),
-
- INIT_PARAM(RASSize, "RAS size"),
-
- INIT_PARAM(LQEntries, "Number of load queue entries"),
- INIT_PARAM(SQEntries, "Number of store queue entries"),
- INIT_PARAM(LFSTSize, "Last fetched store table size"),
- INIT_PARAM(SSITSize, "Store set ID table size"),
-
- INIT_PARAM(numPhysIntRegs, "Number of physical integer registers"),
- INIT_PARAM(numPhysFloatRegs, "Number of physical floating point "
- "registers"),
- INIT_PARAM(numIQEntries, "Number of instruction queue entries"),
- INIT_PARAM(numROBEntries, "Number of reorder buffer entries"),
-
- INIT_PARAM_DFLT(smtNumFetchingThreads, "SMT Number of Fetching Threads", 1),
- INIT_PARAM_DFLT(smtFetchPolicy, "SMT Fetch Policy", "SingleThread"),
- INIT_PARAM_DFLT(smtLSQPolicy, "SMT LSQ Sharing Policy", "Partitioned"),
- INIT_PARAM_DFLT(smtLSQThreshold,"SMT LSQ Threshold", 100),
- INIT_PARAM_DFLT(smtIQPolicy, "SMT IQ Policy", "Partitioned"),
- INIT_PARAM_DFLT(smtIQThreshold, "SMT IQ Threshold", 100),
- INIT_PARAM_DFLT(smtROBPolicy, "SMT ROB Sharing Policy", "Partitioned"),
- INIT_PARAM_DFLT(smtROBThreshold,"SMT ROB Threshold", 100),
- INIT_PARAM_DFLT(smtCommitPolicy,"SMT Commit Fetch Policy", "RoundRobin"),
-
- INIT_PARAM(instShiftAmt, "Number of bits to shift instructions by"),
- INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
-
- INIT_PARAM(function_trace, "Enable function trace"),
- INIT_PARAM(function_trace_start, "Cycle to start function trace")
-
-END_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
-
-CREATE_SIM_OBJECT(DerivAlphaFullCPU)
-{
- DerivAlphaFullCPU *cpu;
-
-#if FULL_SYSTEM
- // Full-system only supports a single thread for the moment.
- int actual_num_threads = 1;
-#else
- // In non-full-system mode, we infer the number of threads from
- // the workload if it's not explicitly specified.
- int actual_num_threads =
- numThreads.isValid() ? numThreads : workload.size();
-
- if (workload.size() == 0) {
- fatal("Must specify at least one workload!");
- }
-
-#endif
-
- AlphaSimpleParams *params = new AlphaSimpleParams;
-
- params->clock = clock;
-
- params->name = getInstanceName();
- params->numberOfThreads = actual_num_threads;
- params->activity = activity;
-
-#if FULL_SYSTEM
- params->system = system;
- params->cpu_id = cpu_id;
- params->itb = itb;
- params->dtb = dtb;
-#else
- params->workload = workload;
-// params->pTable = page_table;
-#endif // FULL_SYSTEM
-
- params->mem = mem;
-
- params->checker = checker;
-
- params->max_insts_any_thread = max_insts_any_thread;
- params->max_insts_all_threads = max_insts_all_threads;
- params->max_loads_any_thread = max_loads_any_thread;
- params->max_loads_all_threads = max_loads_all_threads;
-
- //
- // Caches
- //
- params->icacheInterface = icache ? icache->getInterface() : NULL;
- params->dcacheInterface = dcache ? dcache->getInterface() : NULL;
- params->cachePorts = cachePorts;
-
- params->decodeToFetchDelay = decodeToFetchDelay;
- params->renameToFetchDelay = renameToFetchDelay;
- params->iewToFetchDelay = iewToFetchDelay;
- params->commitToFetchDelay = commitToFetchDelay;
- params->fetchWidth = fetchWidth;
-
- params->renameToDecodeDelay = renameToDecodeDelay;
- params->iewToDecodeDelay = iewToDecodeDelay;
- params->commitToDecodeDelay = commitToDecodeDelay;
- params->fetchToDecodeDelay = fetchToDecodeDelay;
- params->decodeWidth = decodeWidth;
-
- params->iewToRenameDelay = iewToRenameDelay;
- params->commitToRenameDelay = commitToRenameDelay;
- params->decodeToRenameDelay = decodeToRenameDelay;
- params->renameWidth = renameWidth;
-
- params->commitToIEWDelay = commitToIEWDelay;
- params->renameToIEWDelay = renameToIEWDelay;
- params->issueToExecuteDelay = issueToExecuteDelay;
- params->issueWidth = issueWidth;
- params->executeWidth = executeWidth;
- params->executeIntWidth = executeIntWidth;
- params->executeFloatWidth = executeFloatWidth;
- params->executeBranchWidth = executeBranchWidth;
- params->executeMemoryWidth = executeMemoryWidth;
- params->fuPool = fuPool;
-
- params->iewToCommitDelay = iewToCommitDelay;
- params->renameToROBDelay = renameToROBDelay;
- params->commitWidth = commitWidth;
- params->squashWidth = squashWidth;
- params->trapLatency = trapLatency;
- params->fetchTrapLatency = fetchTrapLatency;
-
- params->predType = predType;
- params->localPredictorSize = localPredictorSize;
- params->localCtrBits = localCtrBits;
- params->localHistoryTableSize = localHistoryTableSize;
- params->localHistoryBits = localHistoryBits;
- params->globalPredictorSize = globalPredictorSize;
- params->globalCtrBits = globalCtrBits;
- params->globalHistoryBits = globalHistoryBits;
- params->choicePredictorSize = choicePredictorSize;
- params->choiceCtrBits = choiceCtrBits;
-
- params->BTBEntries = BTBEntries;
- params->BTBTagSize = BTBTagSize;
-
- params->RASSize = RASSize;
-
- params->LQEntries = LQEntries;
- params->SQEntries = SQEntries;
-
- params->SSITSize = SSITSize;
- params->LFSTSize = LFSTSize;
-
- params->numPhysIntRegs = numPhysIntRegs;
- params->numPhysFloatRegs = numPhysFloatRegs;
- params->numIQEntries = numIQEntries;
- params->numROBEntries = numROBEntries;
-
- params->smtNumFetchingThreads = smtNumFetchingThreads;
- params->smtFetchPolicy = smtFetchPolicy;
- params->smtIQPolicy = smtIQPolicy;
- params->smtLSQPolicy = smtLSQPolicy;
- params->smtLSQThreshold = smtLSQThreshold;
- params->smtROBPolicy = smtROBPolicy;
- params->smtROBThreshold = smtROBThreshold;
- params->smtCommitPolicy = smtCommitPolicy;
-
- params->instShiftAmt = 2;
-
- params->deferRegistration = defer_registration;
-
- params->functionTrace = function_trace;
- params->functionTraceStart = function_trace_start;
-
- cpu = new DerivAlphaFullCPU(params);
-
- return cpu;
-}
-
-REGISTER_SIM_OBJECT("DerivAlphaFullCPU", DerivAlphaFullCPU)
-
diff --git a/cpu/o3/alpha_cpu_impl.hh b/cpu/o3/alpha_cpu_impl.hh
deleted file mode 100644
index f39fdf6b6..000000000
--- a/cpu/o3/alpha_cpu_impl.hh
+++ /dev/null
@@ -1,782 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "arch/alpha/faults.hh"
-#include "base/cprintf.hh"
-#include "base/statistics.hh"
-#include "base/timebuf.hh"
-#include "cpu/checker/exec_context.hh"
-#include "mem/mem_interface.hh"
-#include "sim/sim_events.hh"
-#include "sim/stats.hh"
-
-#include "cpu/o3/alpha_cpu.hh"
-#include "cpu/o3/alpha_params.hh"
-#include "cpu/o3/comm.hh"
-#include "cpu/o3/thread_state.hh"
-
-#if FULL_SYSTEM
-#include "arch/alpha/osfpal.hh"
-#include "arch/isa_traits.hh"
-#include "cpu/quiesce_event.hh"
-#include "kern/kernel_stats.hh"
-#endif
-
-using namespace TheISA;
-
-template <class Impl>
-AlphaFullCPU<Impl>::AlphaFullCPU(Params *params)
-#if FULL_SYSTEM
- : FullO3CPU<Impl>(params), itb(params->itb), dtb(params->dtb)
-#else
- : FullO3CPU<Impl>(params)
-#endif
-{
- DPRINTF(FullCPU, "AlphaFullCPU: Creating AlphaFullCPU object.\n");
-
- // Setup any thread state.
- this->thread.resize(this->numThreads);
-
- for (int i = 0; i < this->numThreads; ++i) {
-#if FULL_SYSTEM
- // SMT is not supported in FS mode yet.
- assert(this->numThreads == 1);
- this->thread[i] = new Thread(this, 0, params->mem);
- this->thread[i]->setStatus(ExecContext::Suspended);
-#else
- if (i < params->workload.size()) {
- DPRINTF(FullCPU, "FullCPU: Workload[%i]'s starting PC is %#x, "
- "process is %#x",
- i, params->workload[i]->prog_entry, this->thread[i]);
- this->thread[i] = new Thread(this, i, params->workload[i], i);
- assert(params->workload[i]->getMemory() != NULL);
-
- this->thread[i]->setStatus(ExecContext::Suspended);
- //usedTids[i] = true;
- //threadMap[i] = i;
- } else {
- //Allocate Empty execution context so M5 can use later
- //when scheduling threads to CPU
- Process* dummy_proc = NULL;
-
- this->thread[i] = new Thread(this, i, dummy_proc, i);
- //usedTids[i] = false;
- }
-#endif // !FULL_SYSTEM
-
- ExecContext *xc_proxy;
-
- // Setup the XC that will serve as the interface to the threads/CPU.
- AlphaXC *alpha_xc = new AlphaXC;
-
- // If we're using a checker, then the XC should be the
- // CheckerExecContext.
- if (params->checker) {
- xc_proxy = new CheckerExecContext<AlphaXC>(
- alpha_xc, this->checker);
- } else {
- xc_proxy = alpha_xc;
- }
-
- alpha_xc->cpu = this;
- alpha_xc->thread = this->thread[i];
-
-#if FULL_SYSTEM
- // Setup quiesce event.
- this->thread[i]->quiesceEvent =
- new EndQuiesceEvent(xc_proxy);
- this->thread[i]->lastActivate = 0;
- this->thread[i]->lastSuspend = 0;
-#endif
- // Give the thread the XC.
- this->thread[i]->xcProxy = xc_proxy;
-
- // Add the XC to the CPU's list of XC's.
- this->execContexts.push_back(xc_proxy);
- }
-
-
- for (int i=0; i < this->numThreads; i++) {
- this->thread[i]->funcExeInst = 0;
- }
-
- // Sets CPU pointers. These must be set at this level because the CPU
- // pointers are defined to be the highest level of CPU class.
- this->fetch.setCPU(this);
- this->decode.setCPU(this);
- this->rename.setCPU(this);
- this->iew.setCPU(this);
- this->commit.setCPU(this);
-
- this->rob.setCPU(this);
- this->regFile.setCPU(this);
-
- lockAddr = 0;
- lockFlag = false;
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::regStats()
-{
- // Register stats for everything that has stats.
- this->fullCPURegStats();
- this->fetch.regStats();
- this->decode.regStats();
- this->rename.regStats();
- this->iew.regStats();
- this->commit.regStats();
-}
-
-#if FULL_SYSTEM
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::dumpFuncProfile()
-{
- // Currently not supported
-}
-#endif
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::takeOverFrom(ExecContext *old_context)
-{
- // some things should already be set up
- assert(getMemPtr() == old_context->getMemPtr());
-#if FULL_SYSTEM
- assert(getSystemPtr() == old_context->getSystemPtr());
-#else
- assert(getProcessPtr() == old_context->getProcessPtr());
-#endif
-
- // copy over functional state
- setStatus(old_context->status());
- copyArchRegs(old_context);
- setCpuId(old_context->readCpuId());
-
-#if !FULL_SYSTEM
- thread->funcExeInst = old_context->readFuncExeInst();
-#else
- EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent();
- if (other_quiesce) {
- // Point the quiesce event's XC at this XC so that it wakes up
- // the proper CPU.
- other_quiesce->xc = this;
- }
- if (thread->quiesceEvent) {
- thread->quiesceEvent->xc = this;
- }
-
- // Transfer kernel stats from one CPU to the other.
- thread->kernelStats = old_context->getKernelStats();
-// storeCondFailures = 0;
- cpu->lockFlag = false;
-#endif
-
- old_context->setStatus(ExecContext::Unallocated);
-
- thread->inSyscall = false;
- thread->trapPending = false;
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::activate(int delay)
-{
- DPRINTF(FullCPU, "Calling activate on AlphaXC\n");
-
- if (thread->status() == ExecContext::Active)
- return;
-
-#if FULL_SYSTEM
- thread->lastActivate = curTick;
-#endif
-
- if (thread->status() == ExecContext::Unallocated) {
- cpu->activateWhenReady(thread->tid);
- return;
- }
-
- thread->setStatus(ExecContext::Active);
-
- // status() == Suspended
- cpu->activateContext(thread->tid, delay);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::suspend()
-{
- DPRINTF(FullCPU, "Calling suspend on AlphaXC\n");
-
- if (thread->status() == ExecContext::Suspended)
- return;
-
-#if FULL_SYSTEM
- thread->lastActivate = curTick;
- thread->lastSuspend = curTick;
-#endif
-/*
-#if FULL_SYSTEM
- // Don't change the status from active if there are pending interrupts
- if (cpu->check_interrupts()) {
- assert(status() == ExecContext::Active);
- return;
- }
-#endif
-*/
- thread->setStatus(ExecContext::Suspended);
- cpu->suspendContext(thread->tid);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::deallocate()
-{
- DPRINTF(FullCPU, "Calling deallocate on AlphaXC\n");
-
- if (thread->status() == ExecContext::Unallocated)
- return;
-
- thread->setStatus(ExecContext::Unallocated);
- cpu->deallocateContext(thread->tid);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::halt()
-{
- DPRINTF(FullCPU, "Calling halt on AlphaXC\n");
-
- if (thread->status() == ExecContext::Halted)
- return;
-
- thread->setStatus(ExecContext::Halted);
- cpu->haltContext(thread->tid);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::regStats(const std::string &name)
-{
-#if FULL_SYSTEM
- thread->kernelStats = new Kernel::Statistics(cpu->system);
- thread->kernelStats->regStats(name + ".kern");
-#endif
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::serialize(std::ostream &os)
-{
-#if FULL_SYSTEM
- if (thread->kernelStats)
- thread->kernelStats->serialize(os);
-#endif
-
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::unserialize(Checkpoint *cp, const std::string &section)
-{
-#if FULL_SYSTEM
- if (thread->kernelStats)
- thread->kernelStats->unserialize(cp, section);
-#endif
-
-}
-
-#if FULL_SYSTEM
-template <class Impl>
-EndQuiesceEvent *
-AlphaFullCPU<Impl>::AlphaXC::getQuiesceEvent()
-{
- return thread->quiesceEvent;
-}
-
-template <class Impl>
-Tick
-AlphaFullCPU<Impl>::AlphaXC::readLastActivate()
-{
- return thread->lastActivate;
-}
-
-template <class Impl>
-Tick
-AlphaFullCPU<Impl>::AlphaXC::readLastSuspend()
-{
- return thread->lastSuspend;
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::profileClear()
-{}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::profileSample()
-{}
-#endif
-
-template <class Impl>
-TheISA::MachInst
-AlphaFullCPU<Impl>::AlphaXC:: getInst()
-{
- return thread->inst;
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::copyArchRegs(ExecContext *xc)
-{
- // This function will mess things up unless the ROB is empty and
- // there are no instructions in the pipeline.
- unsigned tid = thread->tid;
- PhysRegIndex renamed_reg;
-
- // First loop through the integer registers.
- for (int i = 0; i < AlphaISA::NumIntRegs; ++i) {
- renamed_reg = cpu->renameMap[tid].lookup(i);
-
- DPRINTF(FullCPU, "FullCPU: Copying over register %i, had data %lli, "
- "now has data %lli.\n",
- renamed_reg, cpu->readIntReg(renamed_reg),
- xc->readIntReg(i));
-
- cpu->setIntReg(renamed_reg, xc->readIntReg(i));
- }
-
- // Then loop through the floating point registers.
- for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) {
- renamed_reg = cpu->renameMap[tid].lookup(i + AlphaISA::FP_Base_DepTag);
- cpu->setFloatRegDouble(renamed_reg,
- xc->readFloatRegDouble(i));
- cpu->setFloatRegInt(renamed_reg,
- xc->readFloatRegInt(i));
- }
-
- // Copy the misc regs.
- cpu->regFile.miscRegs[tid].copyMiscRegs(xc);
-
- // Then finally set the PC and the next PC.
- cpu->setPC(xc->readPC(), tid);
- cpu->setNextPC(xc->readNextPC(), tid);
-#if !FULL_SYSTEM
- this->thread->funcExeInst = xc->readFuncExeInst();
-#endif
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::clearArchRegs()
-{}
-
-template <class Impl>
-uint64_t
-AlphaFullCPU<Impl>::AlphaXC::readIntReg(int reg_idx)
-{
- return cpu->readArchIntReg(reg_idx, thread->tid);
-}
-
-template <class Impl>
-float
-AlphaFullCPU<Impl>::AlphaXC::readFloatRegSingle(int reg_idx)
-{
- return cpu->readArchFloatRegSingle(reg_idx, thread->tid);
-}
-
-template <class Impl>
-double
-AlphaFullCPU<Impl>::AlphaXC::readFloatRegDouble(int reg_idx)
-{
- return cpu->readArchFloatRegDouble(reg_idx, thread->tid);
-}
-
-template <class Impl>
-uint64_t
-AlphaFullCPU<Impl>::AlphaXC::readFloatRegInt(int reg_idx)
-{
- return cpu->readArchFloatRegInt(reg_idx, thread->tid);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::setIntReg(int reg_idx, uint64_t val)
-{
- cpu->setArchIntReg(reg_idx, val, thread->tid);
-
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromXC(thread->tid);
- }
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::setFloatRegSingle(int reg_idx, float val)
-{
- cpu->setArchFloatRegSingle(reg_idx, val, thread->tid);
-
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromXC(thread->tid);
- }
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::setFloatRegDouble(int reg_idx, double val)
-{
- cpu->setArchFloatRegDouble(reg_idx, val, thread->tid);
-
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromXC(thread->tid);
- }
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::setFloatRegInt(int reg_idx, uint64_t val)
-{
- cpu->setArchFloatRegInt(reg_idx, val, thread->tid);
-
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromXC(thread->tid);
- }
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::setPC(uint64_t val)
-{
- cpu->setPC(val, thread->tid);
-
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromXC(thread->tid);
- }
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::setNextPC(uint64_t val)
-{
- cpu->setNextPC(val, thread->tid);
-
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromXC(thread->tid);
- }
-}
-
-template <class Impl>
-Fault
-AlphaFullCPU<Impl>::AlphaXC::setMiscReg(int misc_reg, const MiscReg &val)
-{
- Fault ret_fault = cpu->setMiscReg(misc_reg, val, thread->tid);
-
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromXC(thread->tid);
- }
-
- return ret_fault;
-}
-
-template <class Impl>
-Fault
-AlphaFullCPU<Impl>::AlphaXC::setMiscRegWithEffect(int misc_reg,
- const MiscReg &val)
-{
- Fault ret_fault = cpu->setMiscRegWithEffect(misc_reg, val, thread->tid);
-
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromXC(thread->tid);
- }
-
- return ret_fault;
-}
-
-#if !FULL_SYSTEM
-
-template <class Impl>
-TheISA::IntReg
-AlphaFullCPU<Impl>::AlphaXC::getSyscallArg(int i)
-{
- return cpu->getSyscallArg(i, thread->tid);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::setSyscallArg(int i, IntReg val)
-{
- cpu->setSyscallArg(i, val, thread->tid);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::setSyscallReturn(SyscallReturn return_value)
-{
- cpu->setSyscallReturn(return_value, thread->tid);
-}
-
-#endif // FULL_SYSTEM
-
-template <class Impl>
-MiscReg
-AlphaFullCPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
-{
- return this->regFile.readMiscReg(misc_reg, tid);
-}
-
-template <class Impl>
-MiscReg
-AlphaFullCPU<Impl>::readMiscRegWithEffect(int misc_reg, Fault &fault,
- unsigned tid)
-{
- return this->regFile.readMiscRegWithEffect(misc_reg, fault, tid);
-}
-
-template <class Impl>
-Fault
-AlphaFullCPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid)
-{
- return this->regFile.setMiscReg(misc_reg, val, tid);
-}
-
-template <class Impl>
-Fault
-AlphaFullCPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val,
- unsigned tid)
-{
- return this->regFile.setMiscRegWithEffect(misc_reg, val, tid);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::squashFromXC(unsigned tid)
-{
- this->thread[tid]->inSyscall = true;
- this->commit.generateXCEvent(tid);
-}
-
-#if FULL_SYSTEM
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::post_interrupt(int int_num, int index)
-{
- BaseCPU::post_interrupt(int_num, index);
-
- if (this->thread[0]->status() == ExecContext::Suspended) {
- DPRINTF(IPI,"Suspended Processor awoke\n");
- this->execContexts[0]->activate();
- }
-}
-
-template <class Impl>
-int
-AlphaFullCPU<Impl>::readIntrFlag()
-{
- return this->regFile.readIntrFlag();
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::setIntrFlag(int val)
-{
- this->regFile.setIntrFlag(val);
-}
-
-template <class Impl>
-Fault
-AlphaFullCPU<Impl>::hwrei(unsigned tid)
-{
- // Need to clear the lock flag upon returning from an interrupt.
- this->lockFlag = false;
-
- this->thread[tid]->kernelStats->hwrei();
-
- this->checkInterrupts = true;
-
- // FIXME: XXX check for interrupts? XXX
- return NoFault;
-}
-
-template <class Impl>
-bool
-AlphaFullCPU<Impl>::simPalCheck(int palFunc, unsigned tid)
-{
- if (this->thread[tid]->kernelStats)
- this->thread[tid]->kernelStats->callpal(palFunc,
- this->execContexts[tid]);
-
- switch (palFunc) {
- case PAL::halt:
- halt();
- if (--System::numSystemsRunning == 0)
- new SimExitEvent("all cpus halted");
- break;
-
- case PAL::bpt:
- case PAL::bugchk:
- if (this->system->breakpoint())
- return false;
- break;
- }
-
- return true;
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::trap(Fault fault, unsigned tid)
-{
- // Pass the thread's XC into the invoke method.
- fault->invoke(this->execContexts[tid]);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::processInterrupts()
-{
- // Check for interrupts here. For now can copy the code that
- // exists within isa_fullsys_traits.hh. Also assume that thread 0
- // is the one that handles the interrupts.
- // @todo: Possibly consolidate the interrupt checking code.
- // @todo: Allow other threads to handle interrupts.
-
- // Check if there are any outstanding interrupts
- //Handle the interrupts
- int ipl = 0;
- int summary = 0;
-
- this->checkInterrupts = false;
-
- if (this->readMiscReg(IPR_ASTRR, 0))
- panic("asynchronous traps not implemented\n");
-
- if (this->readMiscReg(IPR_SIRR, 0)) {
- for (int i = INTLEVEL_SOFTWARE_MIN;
- i < INTLEVEL_SOFTWARE_MAX; i++) {
- if (this->readMiscReg(IPR_SIRR, 0) & (ULL(1) << i)) {
- // See table 4-19 of the 21164 hardware reference
- ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- uint64_t interrupts = this->intr_status();
-
- if (interrupts) {
- for (int i = INTLEVEL_EXTERNAL_MIN;
- i < INTLEVEL_EXTERNAL_MAX; i++) {
- if (interrupts & (ULL(1) << i)) {
- // See table 4-19 of the 21164 hardware reference
- ipl = i;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- if (ipl && ipl > this->readMiscReg(IPR_IPLR, 0)) {
- this->setMiscReg(IPR_ISR, summary, 0);
- this->setMiscReg(IPR_INTID, ipl, 0);
- // Checker needs to know these two registers were updated.
- if (this->checker) {
- this->checker->cpuXCBase()->setMiscReg(IPR_ISR, summary);
- this->checker->cpuXCBase()->setMiscReg(IPR_INTID, ipl);
- }
- this->trap(Fault(new InterruptFault), 0);
- DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
- this->readMiscReg(IPR_IPLR, 0), ipl, summary);
- }
-}
-
-#endif // FULL_SYSTEM
-
-#if !FULL_SYSTEM
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::syscall(int tid)
-{
- DPRINTF(FullCPU, "AlphaFullCPU: [tid:%i] Executing syscall().\n\n", tid);
-
- DPRINTF(Activity,"Activity: syscall() called.\n");
-
- // Temporarily increase this by one to account for the syscall
- // instruction.
- ++(this->thread[tid]->funcExeInst);
-
- // Execute the actual syscall.
- this->thread[tid]->syscall();
-
- // Decrease funcExeInst by one as the normal commit will handle
- // incrementing it.
- --(this->thread[tid]->funcExeInst);
-}
-
-template <class Impl>
-TheISA::IntReg
-AlphaFullCPU<Impl>::getSyscallArg(int i, int tid)
-{
- return this->readArchIntReg(AlphaISA::ArgumentReg0 + i, tid);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::setSyscallArg(int i, IntReg val, int tid)
-{
- this->setArchIntReg(AlphaISA::ArgumentReg0 + i, val, tid);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
-{
- // check for error condition. Alpha syscall convention is to
- // indicate success/failure in reg a3 (r19) and put the
- // return value itself in the standard return value reg (v0).
- if (return_value.successful()) {
- // no error
- this->setArchIntReg(SyscallSuccessReg, 0, tid);
- this->setArchIntReg(ReturnValueReg, return_value.value(), tid);
- } else {
- // got an error, return details
- this->setArchIntReg(SyscallSuccessReg, (IntReg) -1, tid);
- this->setArchIntReg(ReturnValueReg, -return_value.value(), tid);
- }
-}
-#endif
diff --git a/cpu/o3/alpha_dyn_inst.cc b/cpu/o3/alpha_dyn_inst.cc
deleted file mode 100644
index 72ac77d95..000000000
--- a/cpu/o3/alpha_dyn_inst.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/o3/alpha_dyn_inst_impl.hh"
-#include "cpu/o3/alpha_impl.hh"
-
-// Force instantiation of AlphaDynInst for all the implementations that
-// are needed.
-template class AlphaDynInst<AlphaSimpleImpl>;
diff --git a/cpu/o3/alpha_dyn_inst.hh b/cpu/o3/alpha_dyn_inst.hh
deleted file mode 100644
index de4d40358..000000000
--- a/cpu/o3/alpha_dyn_inst.hh
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_ALPHA_DYN_INST_HH__
-#define __CPU_O3_ALPHA_DYN_INST_HH__
-
-#include "cpu/base_dyn_inst.hh"
-#include "cpu/inst_seq.hh"
-#include "cpu/o3/alpha_cpu.hh"
-#include "cpu/o3/alpha_impl.hh"
-
-/**
- * Mostly implementation & ISA specific AlphaDynInst. As with most
- * other classes in the new CPU model, it is templated on the Impl to
- * allow for passing in of all types, such as the CPU type and the ISA
- * type. The AlphaDynInst serves as the primary interface to the CPU
- * for instructions that are executing.
- */
-template <class Impl>
-class AlphaDynInst : public BaseDynInst<Impl>
-{
- public:
- /** Typedef for the CPU. */
- typedef typename Impl::FullCPU FullCPU;
-
- /** Binary machine instruction type. */
- typedef TheISA::MachInst MachInst;
- /** Extended machine instruction type. */
- typedef TheISA::ExtMachInst ExtMachInst;
- /** Logical register index type. */
- typedef TheISA::RegIndex RegIndex;
- /** Integer register index type. */
- typedef TheISA::IntReg IntReg;
- /** Misc register index type. */
- typedef TheISA::MiscReg MiscReg;
-
- enum {
- MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs
- MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs
- };
-
- public:
- /** BaseDynInst constructor given a binary instruction. */
- AlphaDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num,
- FullCPU *cpu);
-
- /** BaseDynInst constructor given a static inst pointer. */
- AlphaDynInst(StaticInstPtr &_staticInst);
-
- /** Executes the instruction.*/
- Fault execute();
-
- /** Initiates the access. Only valid for memory operations. */
- Fault initiateAcc();
-
- /** Completes the access. Only valid for memory operations. */
- Fault completeAcc();
-
- private:
- /** Initializes variables. */
- void initVars();
-
- public:
- /** Reads a miscellaneous register. */
- MiscReg readMiscReg(int misc_reg)
- {
- return this->cpu->readMiscReg(misc_reg, this->threadNumber);
- }
-
- /** Reads a misc. register, including any side-effects the read
- * might have as defined by the architecture.
- */
- MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
- {
- return this->cpu->readMiscRegWithEffect(misc_reg, fault,
- this->threadNumber);
- }
-
- /** Sets a misc. register. */
- Fault setMiscReg(int misc_reg, const MiscReg &val)
- {
- this->instResult.integer = val;
- return this->cpu->setMiscReg(misc_reg, val, this->threadNumber);
- }
-
- /** Sets a misc. register, including any side-effects the write
- * might have as defined by the architecture.
- */
- Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
- {
- return this->cpu->setMiscRegWithEffect(misc_reg, val,
- this->threadNumber);
- }
-
-#if FULL_SYSTEM
- /** Calls hardware return from error interrupt. */
- Fault hwrei();
- /** Reads interrupt flag. */
- int readIntrFlag();
- /** Sets interrupt flag. */
- void setIntrFlag(int val);
- /** Checks if system is in PAL mode. */
- bool inPalMode();
- /** Traps to handle specified fault. */
- void trap(Fault fault);
- bool simPalCheck(int palFunc);
-#else
- /** Calls a syscall. */
- void syscall();
-#endif
-
- private:
- /** Physical register index of the destination registers of this
- * instruction.
- */
- PhysRegIndex _destRegIdx[MaxInstDestRegs];
-
- /** Physical register index of the source registers of this
- * instruction.
- */
- PhysRegIndex _srcRegIdx[MaxInstSrcRegs];
-
- /** Physical register index of the previous producers of the
- * architected destinations.
- */
- PhysRegIndex _prevDestRegIdx[MaxInstDestRegs];
-
- public:
-
- // The register accessor methods provide the index of the
- // instruction's operand (e.g., 0 or 1), not the architectural
- // register index, to simplify the implementation of register
- // renaming. We find the architectural register index by indexing
- // into the instruction's own operand index table. Note that a
- // raw pointer to the StaticInst is provided instead of a
- // ref-counted StaticInstPtr to redice overhead. This is fine as
- // long as these methods don't copy the pointer into any long-term
- // storage (which is pretty hard to imagine they would have reason
- // to do).
-
- uint64_t readIntReg(const StaticInst *si, int idx)
- {
- return this->cpu->readIntReg(_srcRegIdx[idx]);
- }
-
- float readFloatRegSingle(const StaticInst *si, int idx)
- {
- return this->cpu->readFloatRegSingle(_srcRegIdx[idx]);
- }
-
- double readFloatRegDouble(const StaticInst *si, int idx)
- {
- return this->cpu->readFloatRegDouble(_srcRegIdx[idx]);
- }
-
- uint64_t readFloatRegInt(const StaticInst *si, int idx)
- {
- return this->cpu->readFloatRegInt(_srcRegIdx[idx]);
- }
-
- /** @todo: Make results into arrays so they can handle multiple dest
- * registers.
- */
- void setIntReg(const StaticInst *si, int idx, uint64_t val)
- {
- this->cpu->setIntReg(_destRegIdx[idx], val);
- BaseDynInst<Impl>::setIntReg(si, idx, val);
- }
-
- void setFloatRegSingle(const StaticInst *si, int idx, float val)
- {
- this->cpu->setFloatRegSingle(_destRegIdx[idx], val);
- BaseDynInst<Impl>::setFloatRegSingle(si, idx, val);
- }
-
- void setFloatRegDouble(const StaticInst *si, int idx, double val)
- {
- this->cpu->setFloatRegDouble(_destRegIdx[idx], val);
- BaseDynInst<Impl>::setFloatRegDouble(si, idx, val);
- }
-
- void setFloatRegInt(const StaticInst *si, int idx, uint64_t val)
- {
- this->cpu->setFloatRegInt(_destRegIdx[idx], val);
- BaseDynInst<Impl>::setFloatRegInt(si, idx, val);
- }
-
- /** Returns the physical register index of the i'th destination
- * register.
- */
- PhysRegIndex renamedDestRegIdx(int idx) const
- {
- return _destRegIdx[idx];
- }
-
- /** Returns the physical register index of the i'th source register. */
- PhysRegIndex renamedSrcRegIdx(int idx) const
- {
- return _srcRegIdx[idx];
- }
-
- /** Returns the physical register index of the previous physical register
- * that remapped to the same logical register index.
- */
- PhysRegIndex prevDestRegIdx(int idx) const
- {
- return _prevDestRegIdx[idx];
- }
-
- /** Renames a destination register to a physical register. Also records
- * the previous physical register that the logical register mapped to.
- */
- void renameDestReg(int idx,
- PhysRegIndex renamed_dest,
- PhysRegIndex previous_rename)
- {
- _destRegIdx[idx] = renamed_dest;
- _prevDestRegIdx[idx] = previous_rename;
- }
-
- /** Renames a source logical register to the physical register which
- * has/will produce that logical register's result.
- * @todo: add in whether or not the source register is ready.
- */
- void renameSrcReg(int idx, PhysRegIndex renamed_src)
- {
- _srcRegIdx[idx] = renamed_src;
- }
-
- public:
- /** Calculates EA part of a memory instruction. Currently unused,
- * though it may be useful in the future if we want to split
- * memory operations into EA calculation and memory access parts.
- */
- Fault calcEA()
- {
- return this->staticInst->eaCompInst()->execute(this, this->traceData);
- }
-
- /** Does the memory access part of a memory instruction. Currently unused,
- * though it may be useful in the future if we want to split
- * memory operations into EA calculation and memory access parts.
- */
- Fault memAccess()
- {
- return this->staticInst->memAccInst()->execute(this, this->traceData);
- }
-};
-
-#endif // __CPU_O3_ALPHA_DYN_INST_HH__
-
diff --git a/cpu/o3/alpha_dyn_inst_impl.hh b/cpu/o3/alpha_dyn_inst_impl.hh
deleted file mode 100644
index d82d46830..000000000
--- a/cpu/o3/alpha_dyn_inst_impl.hh
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/o3/alpha_dyn_inst.hh"
-
-template <class Impl>
-AlphaDynInst<Impl>::AlphaDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC,
- InstSeqNum seq_num, FullCPU *cpu)
- : BaseDynInst<Impl>(inst, PC, Pred_PC, seq_num, cpu)
-{
- initVars();
-}
-
-template <class Impl>
-AlphaDynInst<Impl>::AlphaDynInst(StaticInstPtr &_staticInst)
- : BaseDynInst<Impl>(_staticInst)
-{
- initVars();
-}
-
-template <class Impl>
-void
-AlphaDynInst<Impl>::initVars()
-{
- // Make sure to have the renamed register entries set to the same
- // as the normal register entries. It will allow the IQ to work
- // without any modifications.
- for (int i = 0; i < this->staticInst->numDestRegs(); i++) {
- _destRegIdx[i] = this->staticInst->destRegIdx(i);
- }
-
- for (int i = 0; i < this->staticInst->numSrcRegs(); i++) {
- _srcRegIdx[i] = this->staticInst->srcRegIdx(i);
- this->_readySrcRegIdx[i] = 0;
- }
-}
-
-template <class Impl>
-Fault
-AlphaDynInst<Impl>::execute()
-{
- // @todo: Pretty convoluted way to avoid squashing from happening
- // when using the XC during an instruction's execution
- // (specifically for instructions that have side-effects that use
- // the XC). Fix this.
- bool in_syscall = this->thread->inSyscall;
- this->thread->inSyscall = true;
-
- this->fault = this->staticInst->execute(this, this->traceData);
-
- this->thread->inSyscall = in_syscall;
-
- return this->fault;
-}
-
-template <class Impl>
-Fault
-AlphaDynInst<Impl>::initiateAcc()
-{
- // @todo: Pretty convoluted way to avoid squashing from happening
- // when using the XC during an instruction's execution
- // (specifically for instructions that have side-effects that use
- // the XC). Fix this.
- bool in_syscall = this->thread->inSyscall;
- this->thread->inSyscall = true;
-
- this->fault = this->staticInst->initiateAcc(this, this->traceData);
-
- this->thread->inSyscall = in_syscall;
-
- return this->fault;
-}
-
-template <class Impl>
-Fault
-AlphaDynInst<Impl>::completeAcc()
-{
- if (this->isLoad()) {
- // Loads need the request's data to complete the access.
- this->fault = this->staticInst->completeAcc(this->req->data,
- this,
- this->traceData);
- } else if (this->isStore()) {
- // Stores need the result of the request to complete their access.
- this->fault = this->staticInst->completeAcc((uint8_t*)&this->req->result,
- this,
- this->traceData);
- } else {
- panic("Unknown type!");
- }
-
- return this->fault;
-}
-
-#if FULL_SYSTEM
-template <class Impl>
-Fault
-AlphaDynInst<Impl>::hwrei()
-{
- // Can only do a hwrei when in pal mode.
- if (!this->cpu->inPalMode(this->readPC()))
- return new AlphaISA::UnimplementedOpcodeFault;
-
- // Set the next PC based on the value of the EXC_ADDR IPR.
- this->setNextPC(this->cpu->readMiscReg(AlphaISA::IPR_EXC_ADDR,
- this->threadNumber));
-
- // Tell CPU to clear any state it needs to if a hwrei is taken.
- this->cpu->hwrei(this->threadNumber);
-
- // FIXME: XXX check for interrupts? XXX
- return NoFault;
-}
-
-template <class Impl>
-int
-AlphaDynInst<Impl>::readIntrFlag()
-{
- return this->cpu->readIntrFlag();
-}
-
-template <class Impl>
-void
-AlphaDynInst<Impl>::setIntrFlag(int val)
-{
- this->cpu->setIntrFlag(val);
-}
-
-template <class Impl>
-bool
-AlphaDynInst<Impl>::inPalMode()
-{
- return this->cpu->inPalMode(this->PC);
-}
-
-template <class Impl>
-void
-AlphaDynInst<Impl>::trap(Fault fault)
-{
- this->cpu->trap(fault, this->threadNumber);
-}
-
-template <class Impl>
-bool
-AlphaDynInst<Impl>::simPalCheck(int palFunc)
-{
- return this->cpu->simPalCheck(palFunc, this->threadNumber);
-}
-#else
-template <class Impl>
-void
-AlphaDynInst<Impl>::syscall()
-{
- this->cpu->syscall(this->threadNumber);
-}
-#endif
-
diff --git a/cpu/o3/alpha_impl.hh b/cpu/o3/alpha_impl.hh
deleted file mode 100644
index f404bd3ec..000000000
--- a/cpu/o3/alpha_impl.hh
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_ALPHA_IMPL_HH__
-#define __CPU_O3_ALPHA_IMPL_HH__
-
-#include "arch/alpha/isa_traits.hh"
-
-#include "cpu/o3/alpha_params.hh"
-#include "cpu/o3/cpu_policy.hh"
-
-// Forward declarations.
-template <class Impl>
-class AlphaDynInst;
-
-template <class Impl>
-class AlphaFullCPU;
-
-/** Implementation specific struct that defines several key types to the
- * CPU, the stages within the CPU, the time buffers, and the DynInst.
- * The struct defines the ISA, the CPU policy, the specific DynInst, the
- * specific FullCPU, and all of the structs from the time buffers to do
- * communication.
- * This is one of the key things that must be defined for each hardware
- * specific CPU implementation.
- */
-struct AlphaSimpleImpl
-{
- /** The type of MachInst. */
- typedef TheISA::MachInst MachInst;
-
- /** The CPU policy to be used, which defines all of the CPU stages. */
- typedef SimpleCPUPolicy<AlphaSimpleImpl> CPUPol;
-
- /** The DynInst type to be used. */
- typedef AlphaDynInst<AlphaSimpleImpl> DynInst;
-
- /** The refcounted DynInst pointer to be used. In most cases this is
- * what should be used, and not DynInst *.
- */
- typedef RefCountingPtr<DynInst> DynInstPtr;
-
- /** The FullCPU type to be used. */
- typedef AlphaFullCPU<AlphaSimpleImpl> FullCPU;
-
- /** The Params to be passed to each stage. */
- typedef AlphaSimpleParams Params;
-
- enum {
- MaxWidth = 8,
- MaxThreads = 4
- };
-};
-
-#endif // __CPU_O3_ALPHA_IMPL_HH__
diff --git a/cpu/o3/alpha_params.hh b/cpu/o3/alpha_params.hh
deleted file mode 100644
index f0836a9fd..000000000
--- a/cpu/o3/alpha_params.hh
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_ALPHA_PARAMS_HH__
-#define __CPU_O3_ALPHA_PARAMS_HH__
-
-#include "cpu/o3/cpu.hh"
-
-//Forward declarations
-class AlphaDTB;
-class AlphaITB;
-class FUPool;
-class FunctionalMemory;
-class MemInterface;
-class Process;
-class System;
-
-/**
- * This file defines the parameters that will be used for the AlphaFullCPU.
- * This must be defined externally so that the Impl can have a params class
- * defined that it can pass to all of the individual stages.
- */
-
-class AlphaSimpleParams : public BaseFullCPU::Params
-{
- public:
-
-#if FULL_SYSTEM
- AlphaITB *itb; AlphaDTB *dtb;
-#else
- std::vector<Process *> workload;
- Process *process;
-#endif // FULL_SYSTEM
-
- //Page Table
-// PageTable *pTable;
-
- FunctionalMemory *mem;
-
- BaseCPU *checker;
-
- unsigned activity;
-
- //
- // Caches
- //
- MemInterface *icacheInterface;
- MemInterface *dcacheInterface;
-
- unsigned cachePorts;
-
- //
- // Fetch
- //
- unsigned decodeToFetchDelay;
- unsigned renameToFetchDelay;
- unsigned iewToFetchDelay;
- unsigned commitToFetchDelay;
- unsigned fetchWidth;
-
- //
- // Decode
- //
- unsigned renameToDecodeDelay;
- unsigned iewToDecodeDelay;
- unsigned commitToDecodeDelay;
- unsigned fetchToDecodeDelay;
- unsigned decodeWidth;
-
- //
- // Rename
- //
- unsigned iewToRenameDelay;
- unsigned commitToRenameDelay;
- unsigned decodeToRenameDelay;
- unsigned renameWidth;
-
- //
- // IEW
- //
- unsigned commitToIEWDelay;
- unsigned renameToIEWDelay;
- unsigned issueToExecuteDelay;
- unsigned issueWidth;
- unsigned executeWidth;
- unsigned executeIntWidth;
- unsigned executeFloatWidth;
- unsigned executeBranchWidth;
- unsigned executeMemoryWidth;
- FUPool *fuPool;
-
- //
- // Commit
- //
- unsigned iewToCommitDelay;
- unsigned renameToROBDelay;
- unsigned commitWidth;
- unsigned squashWidth;
- Tick trapLatency;
- Tick fetchTrapLatency;
-
- //
- // Branch predictor (BP, BTB, RAS)
- //
- std::string predType;
- unsigned localPredictorSize;
- unsigned localCtrBits;
- unsigned localHistoryTableSize;
- unsigned localHistoryBits;
- unsigned globalPredictorSize;
- unsigned globalCtrBits;
- unsigned globalHistoryBits;
- unsigned choicePredictorSize;
- unsigned choiceCtrBits;
-
- unsigned BTBEntries;
- unsigned BTBTagSize;
-
- unsigned RASSize;
-
- //
- // Load store queue
- //
- unsigned LQEntries;
- unsigned SQEntries;
-
- //
- // Memory dependence
- //
- unsigned SSITSize;
- unsigned LFSTSize;
-
- //
- // Miscellaneous
- //
- unsigned numPhysIntRegs;
- unsigned numPhysFloatRegs;
- unsigned numIQEntries;
- unsigned numROBEntries;
-
- //SMT Parameters
- unsigned smtNumFetchingThreads;
-
- std::string smtFetchPolicy;
-
- std::string smtIQPolicy;
- unsigned smtIQThreshold;
-
- std::string smtLSQPolicy;
- unsigned smtLSQThreshold;
-
- std::string smtCommitPolicy;
-
- std::string smtROBPolicy;
- unsigned smtROBThreshold;
-
- // Probably can get this from somewhere.
- unsigned instShiftAmt;
-};
-
-#endif // __CPU_O3_ALPHA_PARAMS_HH__
diff --git a/cpu/o3/bpred_unit.cc b/cpu/o3/bpred_unit.cc
deleted file mode 100644
index e149b8073..000000000
--- a/cpu/o3/bpred_unit.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/o3/bpred_unit_impl.hh"
-#include "cpu/o3/alpha_impl.hh"
-#include "cpu/o3/alpha_dyn_inst.hh"
-#include "cpu/ozone/ozone_impl.hh"
-#include "cpu/ozone/simple_impl.hh"
-
-template class BPredUnit<AlphaSimpleImpl>;
-template class BPredUnit<OzoneImpl>;
-template class BPredUnit<SimpleImpl>;
diff --git a/cpu/o3/bpred_unit.hh b/cpu/o3/bpred_unit.hh
deleted file mode 100644
index 93aae8f15..000000000
--- a/cpu/o3/bpred_unit.hh
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_BPRED_UNIT_HH__
-#define __CPU_O3_BPRED_UNIT_HH__
-
-// For Addr type.
-#include "arch/isa_traits.hh"
-#include "base/statistics.hh"
-#include "cpu/inst_seq.hh"
-
-#include "cpu/o3/2bit_local_pred.hh"
-#include "cpu/o3/btb.hh"
-#include "cpu/o3/ras.hh"
-#include "cpu/o3/tournament_pred.hh"
-
-#include <list>
-
-/**
- * Basically a wrapper class to hold both the branch predictor
- * and the BTB.
- */
-template<class Impl>
-class BPredUnit
-{
- private:
- typedef typename Impl::Params Params;
- typedef typename Impl::DynInstPtr DynInstPtr;
-
- enum PredType {
- Local,
- Tournament
- };
-
- PredType predictor;
-
- public:
-
- /**
- * @param params The params object, that has the size of the BP and BTB.
- */
- BPredUnit(Params *params);
-
- /**
- * Registers statistics.
- */
- void regStats();
-
- void switchOut();
-
- void takeOverFrom();
-
- /**
- * Predicts whether or not the instruction is a taken branch, and the
- * target of the branch if it is taken.
- * @param inst The branch instruction.
- * @param PC The predicted PC is passed back through this parameter.
- * @param tid The thread id.
- * @return Returns if the branch is taken or not.
- */
- bool predict(DynInstPtr &inst, Addr &PC, unsigned tid);
-
- // @todo: Rename this function.
- void BPUncond(void * &bp_history);
-
- /**
- * Tells the branch predictor to commit any updates until the given
- * sequence number.
- * @param done_sn The sequence number to commit any older updates up until.
- * @param tid The thread id.
- */
- void update(const InstSeqNum &done_sn, unsigned tid);
-
- /**
- * Squashes all outstanding updates until a given sequence number.
- * @param squashed_sn The sequence number to squash any younger updates up
- * until.
- * @param tid The thread id.
- */
- void squash(const InstSeqNum &squashed_sn, unsigned tid);
-
- /**
- * Squashes all outstanding updates until a given sequence number, and
- * corrects that sn's update with the proper address and taken/not taken.
- * @param squashed_sn The sequence number to squash any younger updates up
- * until.
- * @param corr_target The correct branch target.
- * @param actually_taken The correct branch direction.
- * @param tid The thread id.
- */
- void squash(const InstSeqNum &squashed_sn, const Addr &corr_target,
- bool actually_taken, unsigned tid);
-
- /**
- * @param bp_history Pointer to the history object. The predictor
- * will need to update any state and delete the object.
- */
- void BPSquash(void *bp_history);
-
- /**
- * Looks up a given PC in the BP to see if it is taken or not taken.
- * @param inst_PC The PC to look up.
- * @param bp_history Pointer that will be set to an object that
- * has the branch predictor state associated with the lookup.
- * @return Whether the branch is taken or not taken.
- */
- bool BPLookup(Addr &inst_PC, void * &bp_history);
-
- /**
- * Looks up a given PC in the BTB to see if a matching entry exists.
- * @param inst_PC The PC to look up.
- * @return Whether the BTB contains the given PC.
- */
- bool BTBValid(Addr &inst_PC)
- { return BTB.valid(inst_PC, 0); }
-
- /**
- * Looks up a given PC in the BTB to get the predicted target.
- * @param inst_PC The PC to look up.
- * @return The address of the target of the branch.
- */
- Addr BTBLookup(Addr &inst_PC)
- { return BTB.lookup(inst_PC, 0); }
-
- /**
- * Updates the BP with taken/not taken information.
- * @param inst_PC The branch's PC that will be updated.
- * @param taken Whether the branch was taken or not taken.
- * @param bp_history Pointer to the branch predictor state that is
- * associated with the branch lookup that is being updated.
- * @todo Make this update flexible enough to handle a global predictor.
- */
- void BPUpdate(Addr &inst_PC, bool taken, void *bp_history);
-
- /**
- * Updates the BTB with the target of a branch.
- * @param inst_PC The branch's PC that will be updated.
- * @param target_PC The branch's target that will be added to the BTB.
- */
- void BTBUpdate(Addr &inst_PC, Addr &target_PC)
- { BTB.update(inst_PC, target_PC,0); }
-
- void dump();
-
- private:
- struct PredictorHistory {
- /**
- * Makes a predictor history struct that contains any
- * information needed to update the predictor, BTB, and RAS.
- */
- PredictorHistory(const InstSeqNum &seq_num, const Addr &inst_PC,
- const bool pred_taken, void *bp_history,
- const unsigned _tid)
- : seqNum(seq_num), PC(inst_PC), RASTarget(0),
- RASIndex(0), tid(_tid), predTaken(pred_taken), usedRAS(0),
- wasCall(0), bpHistory(bp_history)
- { }
-
- /** The sequence number for the predictor history entry. */
- InstSeqNum seqNum;
-
- /** The PC associated with the sequence number. */
- Addr PC;
-
- /** The RAS target (only valid if a return). */
- Addr RASTarget;
-
- /** The RAS index of the instruction (only valid if a call). */
- unsigned RASIndex;
-
- /** The thread id. */
- unsigned tid;
-
- /** Whether or not it was predicted taken. */
- bool predTaken;
-
- /** Whether or not the RAS was used. */
- bool usedRAS;
-
- /** Whether or not the instruction was a call. */
- bool wasCall;
-
- /** Pointer to the history object passed back from the branch
- * predictor. It is used to update or restore state of the
- * branch predictor.
- */
- void *bpHistory;
- };
-
- typedef std::list<PredictorHistory> History;
-
- /**
- * The per-thread predictor history. This is used to update the predictor
- * as instructions are committed, or restore it to the proper state after
- * a squash.
- */
- History predHist[Impl::MaxThreads];
-
- /** The local branch predictor. */
- LocalBP *localBP;
-
- /** The tournament branch predictor. */
- TournamentBP *tournamentBP;
-
- /** The BTB. */
- DefaultBTB BTB;
-
- /** The per-thread return address stack. */
- ReturnAddrStack RAS[Impl::MaxThreads];
-
- /** Stat for number of BP lookups. */
- Stats::Scalar<> lookups;
- /** Stat for number of conditional branches predicted. */
- Stats::Scalar<> condPredicted;
- /** Stat for number of conditional branches predicted incorrectly. */
- Stats::Scalar<> condIncorrect;
- /** Stat for number of BTB lookups. */
- Stats::Scalar<> BTBLookups;
- /** Stat for number of BTB hits. */
- Stats::Scalar<> BTBHits;
- /** Stat for number of times the BTB is correct. */
- Stats::Scalar<> BTBCorrect;
- /** Stat for number of times the RAS is used to get a target. */
- Stats::Scalar<> usedRAS;
- /** Stat for number of times the RAS is incorrect. */
- Stats::Scalar<> RASIncorrect;
-};
-
-#endif // __CPU_O3_BPRED_UNIT_HH__
diff --git a/cpu/o3/bpred_unit_impl.hh b/cpu/o3/bpred_unit_impl.hh
deleted file mode 100644
index 1844c155e..000000000
--- a/cpu/o3/bpred_unit_impl.hh
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <list>
-#include <vector>
-
-#include "base/trace.hh"
-#include "base/traceflags.hh"
-#include "cpu/o3/bpred_unit.hh"
-
-using namespace std;
-
-template<class Impl>
-BPredUnit<Impl>::BPredUnit(Params *params)
- : BTB(params->BTBEntries,
- params->BTBTagSize,
- params->instShiftAmt)
-{
- // Setup the selected predictor.
- if (params->predType == "local") {
- localBP = new LocalBP(params->localPredictorSize,
- params->localCtrBits,
- params->instShiftAmt);
- predictor = Local;
- } else if (params->predType == "tournament") {
- tournamentBP = new TournamentBP(params->localPredictorSize,
- params->localCtrBits,
- params->localHistoryTableSize,
- params->localHistoryBits,
- params->globalPredictorSize,
- params->globalHistoryBits,
- params->globalCtrBits,
- params->choicePredictorSize,
- params->choiceCtrBits,
- params->instShiftAmt);
- predictor = Tournament;
- } else {
- fatal("Invalid BP selected!");
- }
-
- for (int i=0; i < Impl::MaxThreads; i++)
- RAS[i].init(params->RASSize);
-}
-
-template <class Impl>
-void
-BPredUnit<Impl>::regStats()
-{
- lookups
- .name(name() + ".BPredUnit.lookups")
- .desc("Number of BP lookups")
- ;
-
- condPredicted
- .name(name() + ".BPredUnit.condPredicted")
- .desc("Number of conditional branches predicted")
- ;
-
- condIncorrect
- .name(name() + ".BPredUnit.condIncorrect")
- .desc("Number of conditional branches incorrect")
- ;
-
- BTBLookups
- .name(name() + ".BPredUnit.BTBLookups")
- .desc("Number of BTB lookups")
- ;
-
- BTBHits
- .name(name() + ".BPredUnit.BTBHits")
- .desc("Number of BTB hits")
- ;
-
- BTBCorrect
- .name(name() + ".BPredUnit.BTBCorrect")
- .desc("Number of correct BTB predictions (this stat may not "
- "work properly.")
- ;
-
- usedRAS
- .name(name() + ".BPredUnit.usedRAS")
- .desc("Number of times the RAS was used to get a target.")
- ;
-
- RASIncorrect
- .name(name() + ".BPredUnit.RASInCorrect")
- .desc("Number of incorrect RAS predictions.")
- ;
-}
-
-template <class Impl>
-void
-BPredUnit<Impl>::switchOut()
-{
- // Clear any state upon switch out.
- for (int i = 0; i < Impl::MaxThreads; ++i) {
- squash(0, i);
- }
-}
-
-template <class Impl>
-void
-BPredUnit<Impl>::takeOverFrom()
-{
- // Can reset all predictor state, but it's not necessarily better
- // than leaving it be.
-/*
- for (int i = 0; i < Impl::MaxThreads; ++i)
- RAS[i].reset();
-
- BP.reset();
- BTB.reset();
-*/
-}
-
-template <class Impl>
-bool
-BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, unsigned tid)
-{
- // See if branch predictor predicts taken.
- // If so, get its target addr either from the BTB or the RAS.
- // Save off record of branch stuff so the RAS can be fixed
- // up once it's done.
-
- using TheISA::MachInst;
-
- bool pred_taken = false;
- Addr target;
-
- ++lookups;
-
- void *bp_history = NULL;
-
- if (inst->isUncondCtrl()) {
- DPRINTF(Fetch, "BranchPred: [tid:%i] Unconditional control.\n", tid);
- pred_taken = true;
- // Tell the BP there was an unconditional branch.
- BPUncond(bp_history);
- } else {
- ++condPredicted;
-
- pred_taken = BPLookup(PC, bp_history);
-
- DPRINTF(Fetch, "BranchPred: [tid:%i]: Branch predictor predicted %i "
- "for PC %#x\n",
- tid, pred_taken, inst->readPC());
- }
-
- PredictorHistory predict_record(inst->seqNum, PC, pred_taken,
- bp_history, tid);
-
- // Now lookup in the BTB or RAS.
- if (pred_taken) {
- if (inst->isReturn()) {
- ++usedRAS;
-
- // If it's a function return call, then look up the address
- // in the RAS.
- target = RAS[tid].top();
-
- // Record the top entry of the RAS, and its index.
- predict_record.usedRAS = true;
- predict_record.RASIndex = RAS[tid].topIdx();
- predict_record.RASTarget = target;
-
- assert(predict_record.RASIndex < 16);
-
- RAS[tid].pop();
-
- DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x is a return, "
- "RAS predicted target: %#x, RAS index: %i.\n",
- tid, inst->readPC(), target, predict_record.RASIndex);
- } else {
- ++BTBLookups;
-
- if (inst->isCall()) {
- RAS[tid].push(PC + sizeof(MachInst));
-
- // Record that it was a call so that the top RAS entry can
- // be popped off if the speculation is incorrect.
- predict_record.wasCall = true;
-
- DPRINTF(Fetch, "BranchPred: [tid:%i] Instruction %#x was a call"
- ", adding %#x to the RAS.\n",
- tid, inst->readPC(), PC + sizeof(MachInst));
- }
-
- if (BTB.valid(PC, tid)) {
- ++BTBHits;
-
- // If it's not a return, use the BTB to get the target addr.
- target = BTB.lookup(PC, tid);
-
- DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x predicted"
- " target is %#x.\n",
- tid, inst->readPC(), target);
-
- } else {
- DPRINTF(Fetch, "BranchPred: [tid:%i]: BTB doesn't have a "
- "valid entry.\n",tid);
- pred_taken = false;
- }
-
- }
- }
-
- if (pred_taken) {
- // Set the PC and the instruction's predicted target.
- PC = target;
- inst->setPredTarg(target);
- } else {
- PC = PC + sizeof(MachInst);
- inst->setPredTarg(PC);
- }
-
- predHist[tid].push_front(predict_record);
-
- DPRINTF(Fetch, "[tid:%i] predHist.size(): %i\n", tid, predHist[tid].size());
-
- return pred_taken;
-}
-
-template <class Impl>
-void
-BPredUnit<Impl>::update(const InstSeqNum &done_sn, unsigned tid)
-{
- DPRINTF(Fetch, "BranchPred: [tid:%i]: Commiting branches until sequence"
- "number %lli.\n", tid, done_sn);
-
- while (!predHist[tid].empty() &&
- predHist[tid].back().seqNum <= done_sn) {
- // Update the branch predictor with the correct results.
- BPUpdate(predHist[tid].back().PC,
- predHist[tid].back().predTaken,
- predHist[tid].back().bpHistory);
-
- predHist[tid].pop_back();
- }
-}
-
-template <class Impl>
-void
-BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, unsigned tid)
-{
- History &pred_hist = predHist[tid];
-
- while (!pred_hist.empty() &&
- pred_hist.front().seqNum > squashed_sn) {
- if (pred_hist.front().usedRAS) {
- DPRINTF(Fetch, "BranchPred: [tid:%i]: Restoring top of RAS to: %i,"
- " target: %#x.\n",
- tid,
- pred_hist.front().RASIndex,
- pred_hist.front().RASTarget);
-
- RAS[tid].restore(pred_hist.front().RASIndex,
- pred_hist.front().RASTarget);
-
- } else if (pred_hist.front().wasCall) {
- DPRINTF(Fetch, "BranchPred: [tid:%i]: Removing speculative entry "
- "added to the RAS.\n",tid);
-
- RAS[tid].pop();
- }
-
- // This call should delete the bpHistory.
- BPSquash(pred_hist.front().bpHistory);
-
- pred_hist.pop_front();
- }
-
-}
-
-template <class Impl>
-void
-BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn,
- const Addr &corr_target,
- const bool actually_taken,
- unsigned tid)
-{
- // Now that we know that a branch was mispredicted, we need to undo
- // all the branches that have been seen up until this branch and
- // fix up everything.
-
- History &pred_hist = predHist[tid];
-
- ++condIncorrect;
-
- DPRINTF(Fetch, "BranchPred: [tid:%i]: Squashing from sequence number %i, "
- "setting target to %#x.\n",
- tid, squashed_sn, corr_target);
-
- squash(squashed_sn, tid);
-
- // If there's a squash due to a syscall, there may not be an entry
- // corresponding to the squash. In that case, don't bother trying to
- // fix up the entry.
- if (!pred_hist.empty()) {
- assert(pred_hist.front().seqNum == squashed_sn);
- if (pred_hist.front().usedRAS) {
- ++RASIncorrect;
- }
-
- BPUpdate(pred_hist.front().PC, actually_taken,
- pred_hist.front().bpHistory);
-
- BTB.update(pred_hist.front().PC, corr_target, tid);
- pred_hist.pop_front();
- }
-}
-
-template <class Impl>
-void
-BPredUnit<Impl>::BPUncond(void * &bp_history)
-{
- // Only the tournament predictor cares about unconditional branches.
- if (predictor == Tournament) {
- tournamentBP->uncondBr(bp_history);
- }
-}
-
-template <class Impl>
-void
-BPredUnit<Impl>::BPSquash(void *bp_history)
-{
- if (predictor == Local) {
- localBP->squash(bp_history);
- } else if (predictor == Tournament) {
- tournamentBP->squash(bp_history);
- } else {
- panic("Predictor type is unexpected value!");
- }
-}
-
-template <class Impl>
-bool
-BPredUnit<Impl>::BPLookup(Addr &inst_PC, void * &bp_history)
-{
- if (predictor == Local) {
- return localBP->lookup(inst_PC, bp_history);
- } else if (predictor == Tournament) {
- return tournamentBP->lookup(inst_PC, bp_history);
- } else {
- panic("Predictor type is unexpected value!");
- }
-}
-
-template <class Impl>
-void
-BPredUnit<Impl>::BPUpdate(Addr &inst_PC, bool taken, void *bp_history)
-{
- if (predictor == Local) {
- localBP->update(inst_PC, taken, bp_history);
- } else if (predictor == Tournament) {
- tournamentBP->update(inst_PC, taken, bp_history);
- } else {
- panic("Predictor type is unexpected value!");
- }
-}
-
-template <class Impl>
-void
-BPredUnit<Impl>::dump()
-{
- typename History::iterator pred_hist_it;
-
- for (int i = 0; i < Impl::MaxThreads; ++i) {
- if (!predHist[i].empty()) {
- pred_hist_it = predHist[i].begin();
-
- cprintf("predHist[%i].size(): %i\n", i, predHist[i].size());
-
- while (pred_hist_it != predHist[i].end()) {
- cprintf("[sn:%lli], PC:%#x, tid:%i, predTaken:%i, "
- "bpHistory:%#x\n",
- (*pred_hist_it).seqNum, (*pred_hist_it).PC,
- (*pred_hist_it).tid, (*pred_hist_it).predTaken,
- (*pred_hist_it).bpHistory);
- pred_hist_it++;
- }
-
- cprintf("\n");
- }
- }
-}
diff --git a/cpu/o3/btb.cc b/cpu/o3/btb.cc
deleted file mode 100644
index e5f69043a..000000000
--- a/cpu/o3/btb.cc
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "base/intmath.hh"
-#include "base/trace.hh"
-#include "cpu/o3/btb.hh"
-
-using namespace TheISA;
-
-DefaultBTB::DefaultBTB(unsigned _numEntries,
- unsigned _tagBits,
- unsigned _instShiftAmt)
- : numEntries(_numEntries),
- tagBits(_tagBits),
- instShiftAmt(_instShiftAmt)
-{
- DPRINTF(Fetch, "BTB: Creating BTB object.\n");
-
- if (!isPowerOf2(numEntries)) {
- fatal("BTB entries is not a power of 2!");
- }
-
- btb.resize(numEntries);
-
- for (int i = 0; i < numEntries; ++i) {
- btb[i].valid = false;
- }
-
- idxMask = numEntries - 1;
-
- tagMask = (1 << tagBits) - 1;
-
- tagShiftAmt = instShiftAmt + floorLog2(numEntries);
-}
-
-void
-DefaultBTB::reset()
-{
- for (int i = 0; i < numEntries; ++i) {
- btb[i].valid = false;
- }
-}
-
-inline
-unsigned
-DefaultBTB::getIndex(const Addr &inst_PC)
-{
- // Need to shift PC over by the word offset.
- return (inst_PC >> instShiftAmt) & idxMask;
-}
-
-inline
-Addr
-DefaultBTB::getTag(const Addr &inst_PC)
-{
- return (inst_PC >> tagShiftAmt) & tagMask;
-}
-
-bool
-DefaultBTB::valid(const Addr &inst_PC, unsigned tid)
-{
- unsigned btb_idx = getIndex(inst_PC);
-
- Addr inst_tag = getTag(inst_PC);
-
- assert(btb_idx < numEntries);
-
- if (btb[btb_idx].valid
- && inst_tag == btb[btb_idx].tag
- && btb[btb_idx].tid == tid) {
- return true;
- } else {
- return false;
- }
-}
-
-// @todo Create some sort of return struct that has both whether or not the
-// address is valid, and also the address. For now will just use addr = 0 to
-// represent invalid entry.
-Addr
-DefaultBTB::lookup(const Addr &inst_PC, unsigned tid)
-{
- unsigned btb_idx = getIndex(inst_PC);
-
- Addr inst_tag = getTag(inst_PC);
-
- assert(btb_idx < numEntries);
-
- if (btb[btb_idx].valid
- && inst_tag == btb[btb_idx].tag
- && btb[btb_idx].tid == tid) {
- return btb[btb_idx].target;
- } else {
- return 0;
- }
-}
-
-void
-DefaultBTB::update(const Addr &inst_PC, const Addr &target, unsigned tid)
-{
- unsigned btb_idx = getIndex(inst_PC);
-
- assert(btb_idx < numEntries);
-
- btb[btb_idx].tid = tid;
- btb[btb_idx].valid = true;
- btb[btb_idx].target = target;
- btb[btb_idx].tag = getTag(inst_PC);
-}
diff --git a/cpu/o3/btb.hh b/cpu/o3/btb.hh
deleted file mode 100644
index b9ff42573..000000000
--- a/cpu/o3/btb.hh
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_BTB_HH__
-#define __CPU_O3_BTB_HH__
-
-// For Addr type.
-#include "arch/isa_traits.hh"
-
-class DefaultBTB
-{
- private:
- struct BTBEntry
- {
- BTBEntry()
- : tag(0), target(0), valid(false)
- {
- }
-
- /** The entry's tag. */
- Addr tag;
-
- /** The entry's target. */
- Addr target;
-
- /** The entry's thread id. */
- unsigned tid;
-
- /** Whether or not the entry is valid. */
- bool valid;
- };
-
- public:
- /** Creates a BTB with the given number of entries, number of bits per
- * tag, and instruction offset amount.
- * @param numEntries Number of entries for the BTB.
- * @param tagBits Number of bits for each tag in the BTB.
- * @param instShiftAmt Offset amount for instructions to ignore alignment.
- */
- DefaultBTB(unsigned numEntries, unsigned tagBits,
- unsigned instShiftAmt);
-
- void reset();
-
- /** Looks up an address in the BTB. Must call valid() first on the address.
- * @param inst_PC The address of the branch to look up.
- * @param tid The thread id.
- * @return Returns the target of the branch.
- */
- Addr lookup(const Addr &inst_PC, unsigned tid);
-
- /** Checks if a branch is in the BTB.
- * @param inst_PC The address of the branch to look up.
- * @param tid The thread id.
- * @return Whether or not the branch exists in the BTB.
- */
- bool valid(const Addr &inst_PC, unsigned tid);
-
- /** Updates the BTB with the target of a branch.
- * @param inst_PC The address of the branch being updated.
- * @param target_PC The target address of the branch.
- * @param tid The thread id.
- */
- void update(const Addr &inst_PC, const Addr &target_PC,
- unsigned tid);
-
- private:
- /** Returns the index into the BTB, based on the branch's PC.
- * @param inst_PC The branch to look up.
- * @return Returns the index into the BTB.
- */
- inline unsigned getIndex(const Addr &inst_PC);
-
- /** Returns the tag bits of a given address.
- * @param inst_PC The branch's address.
- * @return Returns the tag bits.
- */
- inline Addr getTag(const Addr &inst_PC);
-
- /** The actual BTB. */
- std::vector<BTBEntry> btb;
-
- /** The number of entries in the BTB. */
- unsigned numEntries;
-
- /** The index mask. */
- unsigned idxMask;
-
- /** The number of tag bits per entry. */
- unsigned tagBits;
-
- /** The tag mask. */
- unsigned tagMask;
-
- /** Number of bits to shift PC when calculating index. */
- unsigned instShiftAmt;
-
- /** Number of bits to shift PC when calculating tag. */
- unsigned tagShiftAmt;
-};
-
-#endif // __CPU_O3_BTB_HH__
diff --git a/cpu/o3/comm.hh b/cpu/o3/comm.hh
deleted file mode 100644
index d9a242a12..000000000
--- a/cpu/o3/comm.hh
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_COMM_HH__
-#define __CPU_O3_COMM_HH__
-
-#include <vector>
-
-#include "arch/faults.hh"
-#include "arch/isa_traits.hh"
-#include "cpu/inst_seq.hh"
-#include "sim/host.hh"
-
-// Typedef for physical register index type. Although the Impl would be the
-// most likely location for this, there are a few classes that need this
-// typedef yet are not templated on the Impl. For now it will be defined here.
-typedef short int PhysRegIndex;
-
-/** Struct that defines the information passed from fetch to decode. */
-template<class Impl>
-struct DefaultFetchDefaultDecode {
- typedef typename Impl::DynInstPtr DynInstPtr;
-
- int size;
-
- DynInstPtr insts[Impl::MaxWidth];
- Fault fetchFault;
- InstSeqNum fetchFaultSN;
- bool clearFetchFault;
-};
-
-/** Struct that defines the information passed from decode to rename. */
-template<class Impl>
-struct DefaultDecodeDefaultRename {
- typedef typename Impl::DynInstPtr DynInstPtr;
-
- int size;
-
- DynInstPtr insts[Impl::MaxWidth];
-};
-
-/** Struct that defines the information passed from rename to IEW. */
-template<class Impl>
-struct DefaultRenameDefaultIEW {
- typedef typename Impl::DynInstPtr DynInstPtr;
-
- int size;
-
- DynInstPtr insts[Impl::MaxWidth];
-};
-
-/** Struct that defines the information passed from IEW to commit. */
-template<class Impl>
-struct DefaultIEWDefaultCommit {
- typedef typename Impl::DynInstPtr DynInstPtr;
-
- int size;
-
- DynInstPtr insts[Impl::MaxWidth];
-
- bool squash[Impl::MaxThreads];
- bool branchMispredict[Impl::MaxThreads];
- bool branchTaken[Impl::MaxThreads];
- uint64_t mispredPC[Impl::MaxThreads];
- uint64_t nextPC[Impl::MaxThreads];
- InstSeqNum squashedSeqNum[Impl::MaxThreads];
-
- bool includeSquashInst[Impl::MaxThreads];
-};
-
-template<class Impl>
-struct IssueStruct {
- typedef typename Impl::DynInstPtr DynInstPtr;
-
- int size;
-
- DynInstPtr insts[Impl::MaxWidth];
-};
-
-/** Struct that defines all backwards communication. */
-template<class Impl>
-struct TimeBufStruct {
- struct decodeComm {
- bool squash;
- bool predIncorrect;
- uint64_t branchAddr;
-
- InstSeqNum doneSeqNum;
-
- // @todo: Might want to package this kind of branch stuff into a single
- // struct as it is used pretty frequently.
- bool branchMispredict;
- bool branchTaken;
- uint64_t mispredPC;
- uint64_t nextPC;
-
- unsigned branchCount;
- };
-
- decodeComm decodeInfo[Impl::MaxThreads];
-
- struct renameComm {
- };
-
- renameComm renameInfo[Impl::MaxThreads];
-
- struct iewComm {
- // Also eventually include skid buffer space.
- bool usedIQ;
- unsigned freeIQEntries;
- bool usedLSQ;
- unsigned freeLSQEntries;
-
- unsigned iqCount;
- unsigned ldstqCount;
-
- unsigned dispatched;
- unsigned dispatchedToLSQ;
- };
-
- iewComm iewInfo[Impl::MaxThreads];
-
- struct commitComm {
- bool usedROB;
- unsigned freeROBEntries;
- bool emptyROB;
-
- bool squash;
- bool robSquashing;
-
- bool branchMispredict;
- bool branchTaken;
- uint64_t mispredPC;
- uint64_t nextPC;
-
- // Represents the instruction that has either been retired or
- // squashed. Similar to having a single bus that broadcasts the
- // retired or squashed sequence number.
- InstSeqNum doneSeqNum;
-
- //Just in case we want to do a commit/squash on a cycle
- //(necessary for multiple ROBs?)
- bool commitInsts;
- InstSeqNum squashSeqNum;
-
- // Communication specifically to the IQ to tell the IQ that it can
- // schedule a non-speculative instruction.
- InstSeqNum nonSpecSeqNum;
-
- // Hack for now to send back an uncached access to the IEW stage.
- typedef typename Impl::DynInstPtr DynInstPtr;
- bool uncached;
- DynInstPtr uncachedLoad;
-
- bool interruptPending;
- bool clearInterrupt;
- };
-
- commitComm commitInfo[Impl::MaxThreads];
-
- bool decodeBlock[Impl::MaxThreads];
- bool decodeUnblock[Impl::MaxThreads];
- bool renameBlock[Impl::MaxThreads];
- bool renameUnblock[Impl::MaxThreads];
- bool iewBlock[Impl::MaxThreads];
- bool iewUnblock[Impl::MaxThreads];
- bool commitBlock[Impl::MaxThreads];
- bool commitUnblock[Impl::MaxThreads];
-};
-
-#endif //__CPU_O3_COMM_HH__
diff --git a/cpu/o3/commit.cc b/cpu/o3/commit.cc
deleted file mode 100644
index fe5e9c1de..000000000
--- a/cpu/o3/commit.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/o3/alpha_dyn_inst.hh"
-#include "cpu/o3/alpha_impl.hh"
-#include "cpu/o3/commit_impl.hh"
-
-template class DefaultCommit<AlphaSimpleImpl>;
diff --git a/cpu/o3/commit.hh b/cpu/o3/commit.hh
deleted file mode 100644
index d93822394..000000000
--- a/cpu/o3/commit.hh
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_COMMIT_HH__
-#define __CPU_O3_COMMIT_HH__
-
-#include "arch/faults.hh"
-#include "base/statistics.hh"
-#include "base/timebuf.hh"
-#include "cpu/exetrace.hh"
-#include "cpu/inst_seq.hh"
-#include "mem/memory_interface.hh"
-
-template <class>
-class O3ThreadState;
-
-/**
- * DefaultCommit handles single threaded and SMT commit. Its width is
- * specified by the parameters; each cycle it tries to commit that
- * many instructions. The SMT policy decides which thread it tries to
- * commit instructions from. Non- speculative instructions must reach
- * the head of the ROB before they are ready to execute; once they
- * reach the head, commit will broadcast the instruction's sequence
- * number to the previous stages so that they can issue/ execute the
- * instruction. Only one non-speculative instruction is handled per
- * cycle. Commit is responsible for handling all back-end initiated
- * redirects. It receives the redirect, and then broadcasts it to all
- * stages, indicating the sequence number they should squash until,
- * and any necessary branch misprediction information as well. It
- * priortizes redirects by instruction's age, only broadcasting a
- * redirect if it corresponds to an instruction that should currently
- * be in the ROB. This is done by tracking the sequence number of the
- * youngest instruction in the ROB, which gets updated to any
- * squashing instruction's sequence number, and only broadcasting a
- * redirect if it corresponds to an older instruction. Commit also
- * supports multiple cycle squashing, to model a ROB that can only
- * remove a certain number of instructions per cycle.
- */
-template<class Impl>
-class DefaultCommit
-{
- public:
- // Typedefs from the Impl.
- typedef typename Impl::FullCPU FullCPU;
- typedef typename Impl::DynInstPtr DynInstPtr;
- typedef typename Impl::Params Params;
- typedef typename Impl::CPUPol CPUPol;
-
- typedef typename CPUPol::RenameMap RenameMap;
- typedef typename CPUPol::ROB ROB;
-
- typedef typename CPUPol::TimeStruct TimeStruct;
- typedef typename CPUPol::FetchStruct FetchStruct;
- typedef typename CPUPol::IEWStruct IEWStruct;
- typedef typename CPUPol::RenameStruct RenameStruct;
-
- typedef typename CPUPol::Fetch Fetch;
- typedef typename CPUPol::IEW IEW;
-
- typedef O3ThreadState<Impl> Thread;
-
- /** Event class used to schedule a squash due to a trap (fault or
- * interrupt) to happen on a specific cycle.
- */
- class TrapEvent : public Event {
- private:
- DefaultCommit<Impl> *commit;
- unsigned tid;
-
- public:
- TrapEvent(DefaultCommit<Impl> *_commit, unsigned _tid);
-
- void process();
- const char *description();
- };
-
- /** Overall commit status. Used to determine if the CPU can deschedule
- * itself due to a lack of activity.
- */
- enum CommitStatus{
- Active,
- Inactive
- };
-
- /** Individual thread status. */
- enum ThreadStatus {
- Running,
- Idle,
- ROBSquashing,
- TrapPending,
- FetchTrapPending
- };
-
- /** Commit policy for SMT mode. */
- enum CommitPolicy {
- Aggressive,
- RoundRobin,
- OldestReady
- };
-
- private:
- /** Overall commit status. */
- CommitStatus _status;
- /** Next commit status, to be set at the end of the cycle. */
- CommitStatus _nextStatus;
- /** Per-thread status. */
- ThreadStatus commitStatus[Impl::MaxThreads];
- /** Commit policy used in SMT mode. */
- CommitPolicy commitPolicy;
-
- public:
- /** Construct a DefaultCommit with the given parameters. */
- DefaultCommit(Params *params);
-
- /** Returns the name of the DefaultCommit. */
- std::string name() const;
-
- /** Registers statistics. */
- void regStats();
-
- /** Sets the CPU pointer. */
- void setCPU(FullCPU *cpu_ptr);
-
- /** Sets the list of threads. */
- void setThreads(std::vector<Thread *> &threads);
-
- /** Sets the main time buffer pointer, used for backwards communication. */
- void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
-
- void setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr);
-
- /** Sets the pointer to the queue coming from rename. */
- void setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr);
-
- /** Sets the pointer to the queue coming from IEW. */
- void setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr);
-
- void setFetchStage(Fetch *fetch_stage);
-
- Fetch *fetchStage;
-
- /** Sets the pointer to the IEW stage. */
- void setIEWStage(IEW *iew_stage);
-
- /** The pointer to the IEW stage. Used solely to ensure that
- * various events (traps, interrupts, syscalls) do not occur until
- * all stores have written back.
- */
- IEW *iewStage;
-
- /** Sets pointer to list of active threads. */
- void setActiveThreads(std::list<unsigned> *at_ptr);
-
- /** Sets pointer to the commited state rename map. */
- void setRenameMap(RenameMap rm_ptr[Impl::MaxThreads]);
-
- /** Sets pointer to the ROB. */
- void setROB(ROB *rob_ptr);
-
- /** Initializes stage by sending back the number of free entries. */
- void initStage();
-
- /** Initializes the switching out of commit. */
- void switchOut();
-
- /** Completes the switch out of commit. */
- void doSwitchOut();
-
- /** Takes over from another CPU's thread. */
- void takeOverFrom();
-
- /** Ticks the commit stage, which tries to commit instructions. */
- void tick();
-
- /** Handles any squashes that are sent from IEW, and adds instructions
- * to the ROB and tries to commit instructions.
- */
- void commit();
-
- /** Returns the number of free ROB entries for a specific thread. */
- unsigned numROBFreeEntries(unsigned tid);
-
- /** Generates an event to schedule a squash due to a trap. */
- void generateTrapEvent(unsigned tid);
-
- /** Records that commit needs to initiate a squash due to an
- * external state update through the XC.
- */
- void generateXCEvent(unsigned tid);
-
- private:
- /** Updates the overall status of commit with the nextStatus, and
- * tell the CPU if commit is active/inactive.
- */
- void updateStatus();
-
- /** Sets the next status based on threads' statuses, which becomes the
- * current status at the end of the cycle.
- */
- void setNextStatus();
-
- /** Checks if the ROB is completed with squashing. This is for the case
- * where the ROB can take multiple cycles to complete squashing.
- */
- bool robDoneSquashing();
-
- /** Returns if any of the threads have the number of ROB entries changed
- * on this cycle. Used to determine if the number of free ROB entries needs
- * to be sent back to previous stages.
- */
- bool changedROBEntries();
-
- /** Squashes all in flight instructions. */
- void squashAll(unsigned tid);
-
- /** Handles squashing due to a trap. */
- void squashFromTrap(unsigned tid);
-
- /** Handles squashing due to an XC write. */
- void squashFromXC(unsigned tid);
-
- /** Commits as many instructions as possible. */
- void commitInsts();
-
- /** Tries to commit the head ROB instruction passed in.
- * @param head_inst The instruction to be committed.
- */
- bool commitHead(DynInstPtr &head_inst, unsigned inst_num);
-
- /** Gets instructions from rename and inserts them into the ROB. */
- void getInsts();
-
- /** Marks completed instructions using information sent from IEW. */
- void markCompletedInsts();
-
- /** Gets the thread to commit, based on the SMT policy. */
- int getCommittingThread();
-
- /** Returns the thread ID to use based on a round robin policy. */
- int roundRobin();
-
- /** Returns the thread ID to use based on an oldest instruction policy. */
- int oldestReady();
-
- public:
- /** Returns the PC of the head instruction of the ROB.
- * @todo: Probably remove this function as it returns only thread 0.
- */
- uint64_t readPC() { return PC[0]; }
-
- /** Returns the PC of a specific thread. */
- uint64_t readPC(unsigned tid) { return PC[tid]; }
-
- /** Sets the PC of a specific thread. */
- void setPC(uint64_t val, unsigned tid) { PC[tid] = val; }
-
- /** Reads the PC of a specific thread. */
- uint64_t readNextPC(unsigned tid) { return nextPC[tid]; }
-
- /** Sets the next PC of a specific thread. */
- void setNextPC(uint64_t val, unsigned tid) { nextPC[tid] = val; }
-
- private:
- /** Time buffer interface. */
- TimeBuffer<TimeStruct> *timeBuffer;
-
- /** Wire to write information heading to previous stages. */
- typename TimeBuffer<TimeStruct>::wire toIEW;
-
- /** Wire to read information from IEW (for ROB). */
- typename TimeBuffer<TimeStruct>::wire robInfoFromIEW;
-
- TimeBuffer<FetchStruct> *fetchQueue;
-
- typename TimeBuffer<FetchStruct>::wire fromFetch;
-
- /** IEW instruction queue interface. */
- TimeBuffer<IEWStruct> *iewQueue;
-
- /** Wire to read information from IEW queue. */
- typename TimeBuffer<IEWStruct>::wire fromIEW;
-
- /** Rename instruction queue interface, for ROB. */
- TimeBuffer<RenameStruct> *renameQueue;
-
- /** Wire to read information from rename queue. */
- typename TimeBuffer<RenameStruct>::wire fromRename;
-
- public:
- /** ROB interface. */
- ROB *rob;
-
- private:
- /** Pointer to FullCPU. */
- FullCPU *cpu;
-
- /** Memory interface. Used for d-cache accesses. */
- MemInterface *dcacheInterface;
-
- /** Vector of all of the threads. */
- std::vector<Thread *> thread;
-
- Fault fetchFault;
-
- int fetchTrapWait;
-
- /** Records that commit has written to the time buffer this cycle. Used for
- * the CPU to determine if it can deschedule itself if there is no activity.
- */
- bool wroteToTimeBuffer;
-
- /** Records if the number of ROB entries has changed this cycle. If it has,
- * then the number of free entries must be re-broadcast.
- */
- bool changedROBNumEntries[Impl::MaxThreads];
-
- /** A counter of how many threads are currently squashing. */
- int squashCounter;
-
- /** Records if a thread has to squash this cycle due to a trap. */
- bool trapSquash[Impl::MaxThreads];
-
- /** Records if a thread has to squash this cycle due to an XC write. */
- bool xcSquash[Impl::MaxThreads];
-
- /** Priority List used for Commit Policy */
- std::list<unsigned> priority_list;
-
- /** IEW to Commit delay, in ticks. */
- unsigned iewToCommitDelay;
-
- /** Commit to IEW delay, in ticks. */
- unsigned commitToIEWDelay;
-
- /** Rename to ROB delay, in ticks. */
- unsigned renameToROBDelay;
-
- unsigned fetchToCommitDelay;
-
- /** Rename width, in instructions. Used so ROB knows how many
- * instructions to get from the rename instruction queue.
- */
- unsigned renameWidth;
-
- /** IEW width, in instructions. Used so ROB knows how many
- * instructions to get from the IEW instruction queue.
- */
- unsigned iewWidth;
-
- /** Commit width, in instructions. */
- unsigned commitWidth;
-
- /** Number of Reorder Buffers */
- unsigned numRobs;
-
- /** Number of Active Threads */
- unsigned numThreads;
-
- /** Is a switch out pending. */
- bool switchPending;
-
- /** Is commit switched out. */
- bool switchedOut;
-
- /** The latency to handle a trap. Used when scheduling trap
- * squash event.
- */
- Tick trapLatency;
-
- Tick fetchTrapLatency;
-
- Tick fetchFaultTick;
-
- /** The commit PC of each thread. Refers to the instruction that
- * is currently being processed/committed.
- */
- Addr PC[Impl::MaxThreads];
-
- /** The next PC of each thread. */
- Addr nextPC[Impl::MaxThreads];
-
- /** The sequence number of the youngest valid instruction in the ROB. */
- InstSeqNum youngestSeqNum[Impl::MaxThreads];
-
- /** Pointer to the list of active threads. */
- std::list<unsigned> *activeThreads;
-
- /** Rename map interface. */
- RenameMap *renameMap[Impl::MaxThreads];
-
- /** Updates commit stats based on this instruction. */
- void updateComInstStats(DynInstPtr &inst);
-
- /** Stat for the total number of committed instructions. */
- Stats::Scalar<> commitCommittedInsts;
- /** Stat for the total number of squashed instructions discarded by commit.
- */
- Stats::Scalar<> commitSquashedInsts;
- /** Stat for the total number of times commit is told to squash.
- * @todo: Actually increment this stat.
- */
- Stats::Scalar<> commitSquashEvents;
- /** Stat for the total number of times commit has had to stall due to a non-
- * speculative instruction reaching the head of the ROB.
- */
- Stats::Scalar<> commitNonSpecStalls;
- /** Stat for the total number of branch mispredicts that caused a squash. */
- Stats::Scalar<> branchMispredicts;
- /** Distribution of the number of committed instructions each cycle. */
- Stats::Distribution<> numCommittedDist;
-
- /** Total number of instructions committed. */
- Stats::Vector<> statComInst;
- /** Total number of software prefetches committed. */
- Stats::Vector<> statComSwp;
- /** Stat for the total number of committed memory references. */
- Stats::Vector<> statComRefs;
- /** Stat for the total number of committed loads. */
- Stats::Vector<> statComLoads;
- /** Total number of committed memory barriers. */
- Stats::Vector<> statComMembars;
- /** Total number of committed branches. */
- Stats::Vector<> statComBranches;
-
- /** Number of cycles where the commit bandwidth limit is reached. */
- Stats::Scalar<> commitEligibleSamples;
- /** Number of instructions not committed due to bandwidth limits. */
- Stats::Vector<> commitEligible;
-};
-
-#endif // __CPU_O3_COMMIT_HH__
diff --git a/cpu/o3/commit_impl.hh b/cpu/o3/commit_impl.hh
deleted file mode 100644
index 798f30294..000000000
--- a/cpu/o3/commit_impl.hh
+++ /dev/null
@@ -1,1308 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <algorithm>
-#include <string>
-
-#include "base/loader/symtab.hh"
-#include "base/timebuf.hh"
-#include "cpu/checker/cpu.hh"
-#include "cpu/exetrace.hh"
-#include "cpu/o3/commit.hh"
-#include "cpu/o3/thread_state.hh"
-
-using namespace std;
-
-template <class Impl>
-DefaultCommit<Impl>::TrapEvent::TrapEvent(DefaultCommit<Impl> *_commit,
- unsigned _tid)
- : Event(&mainEventQueue, CPU_Tick_Pri), commit(_commit), tid(_tid)
-{
- this->setFlags(Event::AutoDelete);
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::TrapEvent::process()
-{
- // This will get reset by commit if it was switched out at the
- // time of this event processing.
- commit->trapSquash[tid] = true;
-}
-
-template <class Impl>
-const char *
-DefaultCommit<Impl>::TrapEvent::description()
-{
- return "Trap event";
-}
-
-template <class Impl>
-DefaultCommit<Impl>::DefaultCommit(Params *params)
- : dcacheInterface(params->dcacheInterface),
- squashCounter(0),
- iewToCommitDelay(params->iewToCommitDelay),
- commitToIEWDelay(params->commitToIEWDelay),
- renameToROBDelay(params->renameToROBDelay),
- fetchToCommitDelay(params->commitToFetchDelay),
- renameWidth(params->renameWidth),
- iewWidth(params->executeWidth),
- commitWidth(params->commitWidth),
- numThreads(params->numberOfThreads),
- switchedOut(false),
- trapLatency(params->trapLatency),
- fetchTrapLatency(params->fetchTrapLatency)
-{
- _status = Active;
- _nextStatus = Inactive;
- string policy = params->smtCommitPolicy;
-
- //Convert string to lowercase
- std::transform(policy.begin(), policy.end(), policy.begin(),
- (int(*)(int)) tolower);
-
- //Assign commit policy
- if (policy == "aggressive"){
- commitPolicy = Aggressive;
-
- DPRINTF(Commit,"Commit Policy set to Aggressive.");
- } else if (policy == "roundrobin"){
- commitPolicy = RoundRobin;
-
- //Set-Up Priority List
- for (int tid=0; tid < numThreads; tid++) {
- priority_list.push_back(tid);
- }
-
- DPRINTF(Commit,"Commit Policy set to Round Robin.");
- } else if (policy == "oldestready"){
- commitPolicy = OldestReady;
-
- DPRINTF(Commit,"Commit Policy set to Oldest Ready.");
- } else {
- assert(0 && "Invalid SMT Commit Policy. Options Are: {Aggressive,"
- "RoundRobin,OldestReady}");
- }
-
- for (int i=0; i < numThreads; i++) {
- commitStatus[i] = Idle;
- changedROBNumEntries[i] = false;
- trapSquash[i] = false;
- xcSquash[i] = false;
- }
-
- fetchFaultTick = 0;
- fetchTrapWait = 0;
-}
-
-template <class Impl>
-std::string
-DefaultCommit<Impl>::name() const
-{
- return cpu->name() + ".commit";
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::regStats()
-{
- using namespace Stats;
- commitCommittedInsts
- .name(name() + ".commitCommittedInsts")
- .desc("The number of committed instructions")
- .prereq(commitCommittedInsts);
- commitSquashedInsts
- .name(name() + ".commitSquashedInsts")
- .desc("The number of squashed insts skipped by commit")
- .prereq(commitSquashedInsts);
- commitSquashEvents
- .name(name() + ".commitSquashEvents")
- .desc("The number of times commit is told to squash")
- .prereq(commitSquashEvents);
- commitNonSpecStalls
- .name(name() + ".commitNonSpecStalls")
- .desc("The number of times commit has been forced to stall to "
- "communicate backwards")
- .prereq(commitNonSpecStalls);
- branchMispredicts
- .name(name() + ".branchMispredicts")
- .desc("The number of times a branch was mispredicted")
- .prereq(branchMispredicts);
- numCommittedDist
- .init(0,commitWidth,1)
- .name(name() + ".COM:committed_per_cycle")
- .desc("Number of insts commited each cycle")
- .flags(Stats::pdf)
- ;
-
- statComInst
- .init(cpu->number_of_threads)
- .name(name() + ".COM:count")
- .desc("Number of instructions committed")
- .flags(total)
- ;
-
- statComSwp
- .init(cpu->number_of_threads)
- .name(name() + ".COM:swp_count")
- .desc("Number of s/w prefetches committed")
- .flags(total)
- ;
-
- statComRefs
- .init(cpu->number_of_threads)
- .name(name() + ".COM:refs")
- .desc("Number of memory references committed")
- .flags(total)
- ;
-
- statComLoads
- .init(cpu->number_of_threads)
- .name(name() + ".COM:loads")
- .desc("Number of loads committed")
- .flags(total)
- ;
-
- statComMembars
- .init(cpu->number_of_threads)
- .name(name() + ".COM:membars")
- .desc("Number of memory barriers committed")
- .flags(total)
- ;
-
- statComBranches
- .init(cpu->number_of_threads)
- .name(name() + ".COM:branches")
- .desc("Number of branches committed")
- .flags(total)
- ;
-
- //
- // Commit-Eligible instructions...
- //
- // -> The number of instructions eligible to commit in those
- // cycles where we reached our commit BW limit (less the number
- // actually committed)
- //
- // -> The average value is computed over ALL CYCLES... not just
- // the BW limited cycles
- //
- // -> The standard deviation is computed only over cycles where
- // we reached the BW limit
- //
- commitEligible
- .init(cpu->number_of_threads)
- .name(name() + ".COM:bw_limited")
- .desc("number of insts not committed due to BW limits")
- .flags(total)
- ;
-
- commitEligibleSamples
- .name(name() + ".COM:bw_lim_events")
- .desc("number cycles where commit BW limit reached")
- ;
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::setCPU(FullCPU *cpu_ptr)
-{
- DPRINTF(Commit, "Commit: Setting CPU pointer.\n");
- cpu = cpu_ptr;
-
- // Commit must broadcast the number of free entries it has at the start of
- // the simulation, so it starts as active.
- cpu->activateStage(FullCPU::CommitIdx);
-
- trapLatency = cpu->cycles(trapLatency);
- fetchTrapLatency = cpu->cycles(fetchTrapLatency);
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::setThreads(vector<Thread *> &threads)
-{
- thread = threads;
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
-{
- DPRINTF(Commit, "Commit: Setting time buffer pointer.\n");
- timeBuffer = tb_ptr;
-
- // Setup wire to send information back to IEW.
- toIEW = timeBuffer->getWire(0);
-
- // Setup wire to read data from IEW (for the ROB).
- robInfoFromIEW = timeBuffer->getWire(-iewToCommitDelay);
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
-{
- DPRINTF(Commit, "Commit: Setting fetch queue pointer.\n");
- fetchQueue = fq_ptr;
-
- // Setup wire to get instructions from rename (for the ROB).
- fromFetch = fetchQueue->getWire(-fetchToCommitDelay);
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
-{
- DPRINTF(Commit, "Commit: Setting rename queue pointer.\n");
- renameQueue = rq_ptr;
-
- // Setup wire to get instructions from rename (for the ROB).
- fromRename = renameQueue->getWire(-renameToROBDelay);
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
-{
- DPRINTF(Commit, "Commit: Setting IEW queue pointer.\n");
- iewQueue = iq_ptr;
-
- // Setup wire to get instructions from IEW.
- fromIEW = iewQueue->getWire(-iewToCommitDelay);
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::setFetchStage(Fetch *fetch_stage)
-{
- fetchStage = fetch_stage;
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::setIEWStage(IEW *iew_stage)
-{
- iewStage = iew_stage;
-}
-
-template<class Impl>
-void
-DefaultCommit<Impl>::setActiveThreads(list<unsigned> *at_ptr)
-{
- DPRINTF(Commit, "Commit: Setting active threads list pointer.\n");
- activeThreads = at_ptr;
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::setRenameMap(RenameMap rm_ptr[])
-{
- DPRINTF(Commit, "Setting rename map pointers.\n");
-
- for (int i=0; i < numThreads; i++) {
- renameMap[i] = &rm_ptr[i];
- }
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::setROB(ROB *rob_ptr)
-{
- DPRINTF(Commit, "Commit: Setting ROB pointer.\n");
- rob = rob_ptr;
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::initStage()
-{
- rob->setActiveThreads(activeThreads);
- rob->resetEntries();
-
- // Broadcast the number of free entries.
- for (int i=0; i < numThreads; i++) {
- toIEW->commitInfo[i].usedROB = true;
- toIEW->commitInfo[i].freeROBEntries = rob->numFreeEntries(i);
- }
-
- cpu->activityThisCycle();
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::switchOut()
-{
- switchPending = true;
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::doSwitchOut()
-{
- switchedOut = true;
- switchPending = false;
- rob->switchOut();
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::takeOverFrom()
-{
- switchedOut = false;
- _status = Active;
- _nextStatus = Inactive;
- for (int i=0; i < numThreads; i++) {
- commitStatus[i] = Idle;
- changedROBNumEntries[i] = false;
- trapSquash[i] = false;
- xcSquash[i] = false;
- }
- squashCounter = 0;
- rob->takeOverFrom();
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::updateStatus()
-{
- // reset ROB changed variable
- list<unsigned>::iterator threads = (*activeThreads).begin();
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
- changedROBNumEntries[tid] = false;
-
- // Also check if any of the threads has a trap pending
- if (commitStatus[tid] == TrapPending ||
- commitStatus[tid] == FetchTrapPending) {
- _nextStatus = Active;
- }
- }
-
- if (_nextStatus == Inactive && _status == Active) {
- DPRINTF(Activity, "Deactivating stage.\n");
- cpu->deactivateStage(FullCPU::CommitIdx);
- } else if (_nextStatus == Active && _status == Inactive) {
- DPRINTF(Activity, "Activating stage.\n");
- cpu->activateStage(FullCPU::CommitIdx);
- }
-
- _status = _nextStatus;
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::setNextStatus()
-{
- int squashes = 0;
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- if (commitStatus[tid] == ROBSquashing) {
- squashes++;
- }
- }
-
- assert(squashes == squashCounter);
-
- // If commit is currently squashing, then it will have activity for the
- // next cycle. Set its next status as active.
- if (squashCounter) {
- _nextStatus = Active;
- }
-}
-
-template <class Impl>
-bool
-DefaultCommit<Impl>::changedROBEntries()
-{
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- if (changedROBNumEntries[tid]) {
- return true;
- }
- }
-
- return false;
-}
-
-template <class Impl>
-unsigned
-DefaultCommit<Impl>::numROBFreeEntries(unsigned tid)
-{
- return rob->numFreeEntries(tid);
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::generateTrapEvent(unsigned tid)
-{
- DPRINTF(Commit, "Generating trap event for [tid:%i]\n", tid);
-
- TrapEvent *trap = new TrapEvent(this, tid);
-
- trap->schedule(curTick + trapLatency);
-
- thread[tid]->trapPending = true;
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::generateXCEvent(unsigned tid)
-{
- DPRINTF(Commit, "Generating XC squash event for [tid:%i]\n", tid);
-
- xcSquash[tid] = true;
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::squashAll(unsigned tid)
-{
- // If we want to include the squashing instruction in the squash,
- // then use one older sequence number.
- // Hopefully this doesn't mess things up. Basically I want to squash
- // all instructions of this thread.
- InstSeqNum squashed_inst = rob->isEmpty() ?
- 0 : rob->readHeadInst(tid)->seqNum - 1;;
-
- // All younger instructions will be squashed. Set the sequence
- // number as the youngest instruction in the ROB (0 in this case.
- // Hopefully nothing breaks.)
- youngestSeqNum[tid] = 0;
-
- rob->squash(squashed_inst, tid);
- changedROBNumEntries[tid] = true;
-
- // Send back the sequence number of the squashed instruction.
- toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
-
- // Send back the squash signal to tell stages that they should
- // squash.
- toIEW->commitInfo[tid].squash = true;
-
- // Send back the rob squashing signal so other stages know that
- // the ROB is in the process of squashing.
- toIEW->commitInfo[tid].robSquashing = true;
-
- toIEW->commitInfo[tid].branchMispredict = false;
-
- toIEW->commitInfo[tid].nextPC = PC[tid];
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::squashFromTrap(unsigned tid)
-{
- squashAll(tid);
-
- DPRINTF(Commit, "Squashing from trap, restarting at PC %#x\n", PC[tid]);
-
- thread[tid]->trapPending = false;
- thread[tid]->inSyscall = false;
-
- trapSquash[tid] = false;
-
- commitStatus[tid] = ROBSquashing;
- cpu->activityThisCycle();
-
- ++squashCounter;
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::squashFromXC(unsigned tid)
-{
- squashAll(tid);
-
- DPRINTF(Commit, "Squashing from XC, restarting at PC %#x\n", PC[tid]);
-
- thread[tid]->inSyscall = false;
- assert(!thread[tid]->trapPending);
-
- commitStatus[tid] = ROBSquashing;
- cpu->activityThisCycle();
-
- xcSquash[tid] = false;
-
- ++squashCounter;
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::tick()
-{
- wroteToTimeBuffer = false;
- _nextStatus = Inactive;
-
- if (switchPending && rob->isEmpty() && !iewStage->hasStoresToWB()) {
- cpu->signalSwitched();
- return;
- }
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- // Check if any of the threads are done squashing. Change the
- // status if they are done.
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- if (commitStatus[tid] == ROBSquashing) {
-
- if (rob->isDoneSquashing(tid)) {
- commitStatus[tid] = Running;
- --squashCounter;
- } else {
- DPRINTF(Commit,"[tid:%u]: Still Squashing, cannot commit any"
- "insts this cycle.\n", tid);
- }
- }
- }
-
- commit();
-
- markCompletedInsts();
-
- threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- if (!rob->isEmpty(tid) && rob->readHeadInst(tid)->readyToCommit()) {
- // The ROB has more instructions it can commit. Its next status
- // will be active.
- _nextStatus = Active;
-
- DynInstPtr inst = rob->readHeadInst(tid);
-
- DPRINTF(Commit,"[tid:%i]: Instruction [sn:%lli] PC %#x is head of"
- " ROB and ready to commit\n",
- tid, inst->seqNum, inst->readPC());
-
- } else if (!rob->isEmpty(tid)) {
- DynInstPtr inst = rob->readHeadInst(tid);
-
- DPRINTF(Commit,"[tid:%i]: Can't commit, Instruction [sn:%lli] PC "
- "%#x is head of ROB and not ready\n",
- tid, inst->seqNum, inst->readPC());
- }
-
- DPRINTF(Commit, "[tid:%i]: ROB has %d insts & %d free entries.\n",
- tid, rob->countInsts(tid), rob->numFreeEntries(tid));
- }
-
-
- if (wroteToTimeBuffer) {
- DPRINTF(Activity, "Activity This Cycle.\n");
- cpu->activityThisCycle();
- }
-
- updateStatus();
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::commit()
-{
-
- //////////////////////////////////////
- // Check for interrupts
- //////////////////////////////////////
-
-#if FULL_SYSTEM
- // Process interrupts if interrupts are enabled, not in PAL mode,
- // and no other traps or external squashes are currently pending.
- // @todo: Allow other threads to handle interrupts.
- if (cpu->checkInterrupts &&
- cpu->check_interrupts() &&
- !cpu->inPalMode(readPC()) &&
- !trapSquash[0] &&
- !xcSquash[0]) {
- // Tell fetch that there is an interrupt pending. This will
- // make fetch wait until it sees a non PAL-mode PC, at which
- // point it stops fetching instructions.
- toIEW->commitInfo[0].interruptPending = true;
-
- // Wait until the ROB is empty and all stores have drained in
- // order to enter the interrupt.
- if (rob->isEmpty() && !iewStage->hasStoresToWB()) {
- // Not sure which thread should be the one to interrupt. For now
- // always do thread 0.
- assert(!thread[0]->inSyscall);
- thread[0]->inSyscall = true;
-
- // CPU will handle implementation of the interrupt.
- cpu->processInterrupts();
-
- // Now squash or record that I need to squash this cycle.
- commitStatus[0] = TrapPending;
-
- // Exit state update mode to avoid accidental updating.
- thread[0]->inSyscall = false;
-
- // Generate trap squash event.
- generateTrapEvent(0);
-
- toIEW->commitInfo[0].clearInterrupt = true;
-
- DPRINTF(Commit, "Interrupt detected.\n");
- } else {
- DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n");
- }
- }
-#endif // FULL_SYSTEM
-
- ////////////////////////////////////
- // Check for any possible squashes, handle them first
- ////////////////////////////////////
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-/*
- if (fromFetch->fetchFault && commitStatus[0] != TrapPending) {
- // Record the fault. Wait until it's empty in the ROB.
- // Then handle the trap. Ignore it if there's already a
- // trap pending as fetch will be redirected.
- fetchFault = fromFetch->fetchFault;
- fetchFaultTick = curTick + fetchTrapLatency;
- commitStatus[0] = FetchTrapPending;
- DPRINTF(Commit, "Fault from fetch recorded. Will trap if the "
- "ROB empties without squashing the fault.\n");
- fetchTrapWait = 0;
- }
-
- // Fetch may tell commit to clear the trap if it's been squashed.
- if (fromFetch->clearFetchFault) {
- DPRINTF(Commit, "Received clear fetch fault signal\n");
- fetchTrapWait = 0;
- if (commitStatus[0] == FetchTrapPending) {
- DPRINTF(Commit, "Clearing fault from fetch\n");
- commitStatus[0] = Running;
- }
- }
-*/
- // Not sure which one takes priority. I think if we have
- // both, that's a bad sign.
- if (trapSquash[tid] == true) {
- assert(!xcSquash[tid]);
- squashFromTrap(tid);
- } else if (xcSquash[tid] == true) {
- squashFromXC(tid);
- }
-
- // Squashed sequence number must be older than youngest valid
- // instruction in the ROB. This prevents squashes from younger
- // instructions overriding squashes from older instructions.
- if (fromIEW->squash[tid] &&
- commitStatus[tid] != TrapPending &&
- fromIEW->squashedSeqNum[tid] <= youngestSeqNum[tid]) {
-
- DPRINTF(Commit, "[tid:%i]: Squashing due to PC %#x [sn:%i]\n",
- tid,
- fromIEW->mispredPC[tid],
- fromIEW->squashedSeqNum[tid]);
-
- DPRINTF(Commit, "[tid:%i]: Redirecting to PC %#x\n",
- tid,
- fromIEW->nextPC[tid]);
-
- commitStatus[tid] = ROBSquashing;
-
- ++squashCounter;
-
- // If we want to include the squashing instruction in the squash,
- // then use one older sequence number.
- InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid];
-
- if (fromIEW->includeSquashInst[tid] == true)
- squashed_inst--;
-
- // All younger instructions will be squashed. Set the sequence
- // number as the youngest instruction in the ROB.
- youngestSeqNum[tid] = squashed_inst;
-
- rob->squash(squashed_inst, tid);
- changedROBNumEntries[tid] = true;
-
- toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
-
- toIEW->commitInfo[tid].squash = true;
-
- // Send back the rob squashing signal so other stages know that
- // the ROB is in the process of squashing.
- toIEW->commitInfo[tid].robSquashing = true;
-
- toIEW->commitInfo[tid].branchMispredict =
- fromIEW->branchMispredict[tid];
-
- toIEW->commitInfo[tid].branchTaken =
- fromIEW->branchTaken[tid];
-
- toIEW->commitInfo[tid].nextPC = fromIEW->nextPC[tid];
-
- toIEW->commitInfo[tid].mispredPC = fromIEW->mispredPC[tid];
-
- if (toIEW->commitInfo[tid].branchMispredict) {
- ++branchMispredicts;
- }
- }
-
- }
-
- setNextStatus();
-
- if (squashCounter != numThreads) {
- // If we're not currently squashing, then get instructions.
- getInsts();
-
- // Try to commit any instructions.
- commitInsts();
- }
-
- //Check for any activity
- threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- if (changedROBNumEntries[tid]) {
- toIEW->commitInfo[tid].usedROB = true;
- toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
-
- if (rob->isEmpty(tid)) {
- toIEW->commitInfo[tid].emptyROB = true;
- }
-
- wroteToTimeBuffer = true;
- changedROBNumEntries[tid] = false;
- }
- }
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::commitInsts()
-{
- ////////////////////////////////////
- // Handle commit
- // Note that commit will be handled prior to putting new
- // instructions in the ROB so that the ROB only tries to commit
- // instructions it has in this current cycle, and not instructions
- // it is writing in during this cycle. Can't commit and squash
- // things at the same time...
- ////////////////////////////////////
-
- DPRINTF(Commit, "Trying to commit instructions in the ROB.\n");
-
- unsigned num_committed = 0;
-
- DynInstPtr head_inst;
-
- // Commit as many instructions as possible until the commit bandwidth
- // limit is reached, or it becomes impossible to commit any more.
- while (num_committed < commitWidth) {
- int commit_thread = getCommittingThread();
-
- if (commit_thread == -1 || !rob->isHeadReady(commit_thread))
- break;
-
- head_inst = rob->readHeadInst(commit_thread);
-
- int tid = head_inst->threadNumber;
-
- assert(tid == commit_thread);
-
- DPRINTF(Commit, "Trying to commit head instruction, [sn:%i] [tid:%i]\n",
- head_inst->seqNum, tid);
-
- // If the head instruction is squashed, it is ready to retire
- // (be removed from the ROB) at any time.
- if (head_inst->isSquashed()) {
-
- DPRINTF(Commit, "Retiring squashed instruction from "
- "ROB.\n");
-
- rob->retireHead(commit_thread);
-
- ++commitSquashedInsts;
-
- // Record that the number of ROB entries has changed.
- changedROBNumEntries[tid] = true;
- } else {
- PC[tid] = head_inst->readPC();
- nextPC[tid] = head_inst->readNextPC();
-
- // Increment the total number of non-speculative instructions
- // executed.
- // Hack for now: it really shouldn't happen until after the
- // commit is deemed to be successful, but this count is needed
- // for syscalls.
- thread[tid]->funcExeInst++;
-
- // Try to commit the head instruction.
- bool commit_success = commitHead(head_inst, num_committed);
-
- if (commit_success) {
- ++num_committed;
-
- changedROBNumEntries[tid] = true;
-
- // Set the doneSeqNum to the youngest committed instruction.
- toIEW->commitInfo[tid].doneSeqNum = head_inst->seqNum;
-
- ++commitCommittedInsts;
-
- // To match the old model, don't count nops and instruction
- // prefetches towards the total commit count.
- if (!head_inst->isNop() && !head_inst->isInstPrefetch()) {
- cpu->instDone(tid);
- }
-
- PC[tid] = nextPC[tid];
- nextPC[tid] = nextPC[tid] + sizeof(TheISA::MachInst);
-#if FULL_SYSTEM
- int count = 0;
- Addr oldpc;
- do {
- // Debug statement. Checks to make sure we're not
- // currently updating state while handling PC events.
- if (count == 0)
- assert(!thread[tid]->inSyscall &&
- !thread[tid]->trapPending);
- oldpc = PC[tid];
- cpu->system->pcEventQueue.service(
- thread[tid]->getXCProxy());
- count++;
- } while (oldpc != PC[tid]);
- if (count > 1) {
- DPRINTF(Commit, "PC skip function event, stopping commit\n");
- break;
- }
-#endif
- } else {
- DPRINTF(Commit, "Unable to commit head instruction PC:%#x "
- "[tid:%i] [sn:%i].\n",
- head_inst->readPC(), tid ,head_inst->seqNum);
- break;
- }
- }
- }
-
- DPRINTF(CommitRate, "%i\n", num_committed);
- numCommittedDist.sample(num_committed);
-
- if (num_committed == commitWidth) {
- commitEligibleSamples++;
- }
-}
-
-template <class Impl>
-bool
-DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
-{
- assert(head_inst);
-
- int tid = head_inst->threadNumber;
-
- // If the instruction is not executed yet, then it will need extra
- // handling. Signal backwards that it should be executed.
- if (!head_inst->isExecuted()) {
- // Keep this number correct. We have not yet actually executed
- // and committed this instruction.
- thread[tid]->funcExeInst--;
-
- head_inst->reachedCommit = true;
-
- if (head_inst->isNonSpeculative() ||
- head_inst->isStoreConditional() ||
- head_inst->isMemBarrier() ||
- head_inst->isWriteBarrier()) {
-
- DPRINTF(Commit, "Encountered a barrier or non-speculative "
- "instruction [sn:%lli] at the head of the ROB, PC %#x.\n",
- head_inst->seqNum, head_inst->readPC());
-
-#if !FULL_SYSTEM
- // Hack to make sure syscalls/memory barriers/quiesces
- // aren't executed until all stores write back their data.
- // This direct communication shouldn't be used for
- // anything other than this.
- if (inst_num > 0 || iewStage->hasStoresToWB())
-#else
- if ((head_inst->isMemBarrier() || head_inst->isWriteBarrier() ||
- head_inst->isQuiesce()) &&
- iewStage->hasStoresToWB())
-#endif
- {
- DPRINTF(Commit, "Waiting for all stores to writeback.\n");
- return false;
- }
-
- toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;
-
- // Change the instruction so it won't try to commit again until
- // it is executed.
- head_inst->clearCanCommit();
-
- ++commitNonSpecStalls;
-
- return false;
- } else if (head_inst->isLoad()) {
- DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %#x.\n",
- head_inst->seqNum, head_inst->readPC());
-
- // Send back the non-speculative instruction's sequence
- // number. Tell the lsq to re-execute the load.
- toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;
- toIEW->commitInfo[tid].uncached = true;
- toIEW->commitInfo[tid].uncachedLoad = head_inst;
-
- head_inst->clearCanCommit();
-
- return false;
- } else {
- panic("Trying to commit un-executed instruction "
- "of unknown type!\n");
- }
- }
-
- if (head_inst->isThreadSync()) {
- // Not handled for now.
- panic("Thread sync instructions are not handled yet.\n");
- }
-
- // Stores mark themselves as completed.
- if (!head_inst->isStore()) {
- head_inst->setCompleted();
- }
-
- // Use checker prior to updating anything due to traps or PC
- // based events.
- if (cpu->checker) {
- cpu->checker->tick(head_inst);
- }
-
- // Check if the instruction caused a fault. If so, trap.
- Fault inst_fault = head_inst->getFault();
-
- if (inst_fault != NoFault) {
- head_inst->setCompleted();
-#if FULL_SYSTEM
- DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n",
- head_inst->seqNum, head_inst->readPC());
-
- if (iewStage->hasStoresToWB() || inst_num > 0) {
- DPRINTF(Commit, "Stores outstanding, fault must wait.\n");
- return false;
- }
-
- if (cpu->checker && head_inst->isStore()) {
- cpu->checker->tick(head_inst);
- }
-
- assert(!thread[tid]->inSyscall);
-
- // Mark that we're in state update mode so that the trap's
- // execution doesn't generate extra squashes.
- thread[tid]->inSyscall = true;
-
- // DTB will sometimes need the machine instruction for when
- // faults happen. So we will set it here, prior to the DTB
- // possibly needing it for its fault.
- thread[tid]->setInst(
- static_cast<TheISA::MachInst>(head_inst->staticInst->machInst));
-
- // Execute the trap. Although it's slightly unrealistic in
- // terms of timing (as it doesn't wait for the full timing of
- // the trap event to complete before updating state), it's
- // needed to update the state as soon as possible. This
- // prevents external agents from changing any specific state
- // that the trap need.
- cpu->trap(inst_fault, tid);
-
- // Exit state update mode to avoid accidental updating.
- thread[tid]->inSyscall = false;
-
- commitStatus[tid] = TrapPending;
-
- // Generate trap squash event.
- generateTrapEvent(tid);
-
- return false;
-#else // !FULL_SYSTEM
- panic("fault (%d) detected @ PC %08p", inst_fault,
- head_inst->PC);
-#endif // FULL_SYSTEM
- }
-
- updateComInstStats(head_inst);
-
- if (head_inst->traceData) {
- head_inst->traceData->setFetchSeq(head_inst->seqNum);
- head_inst->traceData->setCPSeq(thread[tid]->numInst);
- head_inst->traceData->finalize();
- head_inst->traceData = NULL;
- }
-
- // Update the commit rename map
- for (int i = 0; i < head_inst->numDestRegs(); i++) {
- renameMap[tid]->setEntry(head_inst->destRegIdx(i),
- head_inst->renamedDestRegIdx(i));
- }
-
- // Finally clear the head ROB entry.
- rob->retireHead(tid);
-
- // Return true to indicate that we have committed an instruction.
- return true;
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::getInsts()
-{
- // Read any renamed instructions and place them into the ROB.
- int insts_to_process = min((int)renameWidth, fromRename->size);
-
- for (int inst_num = 0; inst_num < insts_to_process; ++inst_num)
- {
- DynInstPtr inst = fromRename->insts[inst_num];
- int tid = inst->threadNumber;
-
- if (!inst->isSquashed() &&
- commitStatus[tid] != ROBSquashing) {
- changedROBNumEntries[tid] = true;
-
- DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ROB.\n",
- inst->readPC(), inst->seqNum, tid);
-
- rob->insertInst(inst);
-
- assert(rob->getThreadEntries(tid) <= rob->getMaxEntries(tid));
-
- youngestSeqNum[tid] = inst->seqNum;
- } else {
- DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was "
- "squashed, skipping.\n",
- inst->readPC(), inst->seqNum, tid);
- }
- }
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::markCompletedInsts()
-{
- // Grab completed insts out of the IEW instruction queue, and mark
- // instructions completed within the ROB.
- for (int inst_num = 0;
- inst_num < fromIEW->size && fromIEW->insts[inst_num];
- ++inst_num)
- {
- if (!fromIEW->insts[inst_num]->isSquashed()) {
- DPRINTF(Commit, "[tid:%i]: Marking PC %#x, [sn:%lli] ready "
- "within ROB.\n",
- fromIEW->insts[inst_num]->threadNumber,
- fromIEW->insts[inst_num]->readPC(),
- fromIEW->insts[inst_num]->seqNum);
-
- // Mark the instruction as ready to commit.
- fromIEW->insts[inst_num]->setCanCommit();
- }
- }
-}
-
-template <class Impl>
-bool
-DefaultCommit<Impl>::robDoneSquashing()
-{
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- if (!rob->isDoneSquashing(tid))
- return false;
- }
-
- return true;
-}
-
-template <class Impl>
-void
-DefaultCommit<Impl>::updateComInstStats(DynInstPtr &inst)
-{
- unsigned thread = inst->threadNumber;
-
- //
- // Pick off the software prefetches
- //
-#ifdef TARGET_ALPHA
- if (inst->isDataPrefetch()) {
- statComSwp[thread]++;
- } else {
- statComInst[thread]++;
- }
-#else
- statComInst[thread]++;
-#endif
-
- //
- // Control Instructions
- //
- if (inst->isControl())
- statComBranches[thread]++;
-
- //
- // Memory references
- //
- if (inst->isMemRef()) {
- statComRefs[thread]++;
-
- if (inst->isLoad()) {
- statComLoads[thread]++;
- }
- }
-
- if (inst->isMemBarrier()) {
- statComMembars[thread]++;
- }
-}
-
-////////////////////////////////////////
-// //
-// SMT COMMIT POLICY MAINTAINED HERE //
-// //
-////////////////////////////////////////
-template <class Impl>
-int
-DefaultCommit<Impl>::getCommittingThread()
-{
- if (numThreads > 1) {
- switch (commitPolicy) {
-
- case Aggressive:
- //If Policy is Aggressive, commit will call
- //this function multiple times per
- //cycle
- return oldestReady();
-
- case RoundRobin:
- return roundRobin();
-
- case OldestReady:
- return oldestReady();
-
- default:
- return -1;
- }
- } else {
- int tid = (*activeThreads).front();
-
- if (commitStatus[tid] == Running ||
- commitStatus[tid] == Idle ||
- commitStatus[tid] == FetchTrapPending) {
- return tid;
- } else {
- return -1;
- }
- }
-}
-
-template<class Impl>
-int
-DefaultCommit<Impl>::roundRobin()
-{
- list<unsigned>::iterator pri_iter = priority_list.begin();
- list<unsigned>::iterator end = priority_list.end();
-
- while (pri_iter != end) {
- unsigned tid = *pri_iter;
-
- if (commitStatus[tid] == Running ||
- commitStatus[tid] == Idle) {
-
- if (rob->isHeadReady(tid)) {
- priority_list.erase(pri_iter);
- priority_list.push_back(tid);
-
- return tid;
- }
- }
-
- pri_iter++;
- }
-
- return -1;
-}
-
-template<class Impl>
-int
-DefaultCommit<Impl>::oldestReady()
-{
- unsigned oldest = 0;
- bool first = true;
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- if (!rob->isEmpty(tid) &&
- (commitStatus[tid] == Running ||
- commitStatus[tid] == Idle ||
- commitStatus[tid] == FetchTrapPending)) {
-
- if (rob->isHeadReady(tid)) {
-
- DynInstPtr head_inst = rob->readHeadInst(tid);
-
- if (first) {
- oldest = tid;
- first = false;
- } else if (head_inst->seqNum < oldest) {
- oldest = tid;
- }
- }
- }
- }
-
- if (!first) {
- return oldest;
- } else {
- return -1;
- }
-}
diff --git a/cpu/o3/cpu.cc b/cpu/o3/cpu.cc
deleted file mode 100644
index 8d72bdc41..000000000
--- a/cpu/o3/cpu.cc
+++ /dev/null
@@ -1,1183 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config/full_system.hh"
-
-#if FULL_SYSTEM
-#include "sim/system.hh"
-#else
-#include "sim/process.hh"
-#endif
-
-#include "cpu/activity.hh"
-#include "cpu/checker/cpu.hh"
-#include "cpu/cpu_exec_context.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/o3/alpha_dyn_inst.hh"
-#include "cpu/o3/alpha_impl.hh"
-#include "cpu/o3/cpu.hh"
-
-#include "sim/root.hh"
-#include "sim/stat_control.hh"
-
-using namespace std;
-
-BaseFullCPU::BaseFullCPU(Params *params)
- : BaseCPU(params), cpu_id(0)
-{
-}
-
-void
-BaseFullCPU::regStats()
-{
- BaseCPU::regStats();
-}
-
-template <class Impl>
-FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c)
- : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
-{
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::TickEvent::process()
-{
- cpu->tick();
-}
-
-template <class Impl>
-const char *
-FullO3CPU<Impl>::TickEvent::description()
-{
- return "FullO3CPU tick event";
-}
-
-template <class Impl>
-FullO3CPU<Impl>::FullO3CPU(Params *params)
- : BaseFullCPU(params),
- tickEvent(this),
- removeInstsThisCycle(false),
- fetch(params),
- decode(params),
- rename(params),
- iew(params),
- commit(params),
-
- regFile(params->numPhysIntRegs, params->numPhysFloatRegs),
-
- freeList(params->numberOfThreads,//number of activeThreads
- TheISA::NumIntRegs, params->numPhysIntRegs,
- TheISA::NumFloatRegs, params->numPhysFloatRegs),
-
- rob(params->numROBEntries, params->squashWidth,
- params->smtROBPolicy, params->smtROBThreshold,
- params->numberOfThreads),
-
- scoreboard(params->numberOfThreads,//number of activeThreads
- TheISA::NumIntRegs, params->numPhysIntRegs,
- TheISA::NumFloatRegs, params->numPhysFloatRegs,
- TheISA::NumMiscRegs * number_of_threads,
- TheISA::ZeroReg),
-
- // For now just have these time buffers be pretty big.
- // @todo: Make these time buffer sizes parameters or derived
- // from latencies
- timeBuffer(5, 5),
- fetchQueue(5, 5),
- decodeQueue(5, 5),
- renameQueue(5, 5),
- iewQueue(5, 5),
- activityRec(NumStages, 10, params->activity),
-
- globalSeqNum(1),
-
-#if FULL_SYSTEM
- system(params->system),
- memCtrl(system->memctrl),
- physmem(system->physmem),
- mem(params->mem),
-#else
-// pTable(params->pTable),
- mem(params->workload[0]->getMemory()),
-#endif // FULL_SYSTEM
- switchCount(0),
- icacheInterface(params->icacheInterface),
- dcacheInterface(params->dcacheInterface),
- deferRegistration(params->deferRegistration),
- numThreads(number_of_threads)
-{
- _status = Idle;
-
- if (params->checker) {
- BaseCPU *temp_checker = params->checker;
- checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
- checker->setMemory(mem);
-#if FULL_SYSTEM
- checker->setSystem(params->system);
-#endif
- } else {
- checker = NULL;
- }
-
-#if !FULL_SYSTEM
- thread.resize(number_of_threads);
- tids.resize(number_of_threads);
-#endif
-
- // The stages also need their CPU pointer setup. However this
- // must be done at the upper level CPU because they have pointers
- // to the upper level CPU, and not this FullO3CPU.
-
- // Set up Pointers to the activeThreads list for each stage
- fetch.setActiveThreads(&activeThreads);
- decode.setActiveThreads(&activeThreads);
- rename.setActiveThreads(&activeThreads);
- iew.setActiveThreads(&activeThreads);
- commit.setActiveThreads(&activeThreads);
-
- // Give each of the stages the time buffer they will use.
- fetch.setTimeBuffer(&timeBuffer);
- decode.setTimeBuffer(&timeBuffer);
- rename.setTimeBuffer(&timeBuffer);
- iew.setTimeBuffer(&timeBuffer);
- commit.setTimeBuffer(&timeBuffer);
-
- // Also setup each of the stages' queues.
- fetch.setFetchQueue(&fetchQueue);
- decode.setFetchQueue(&fetchQueue);
- commit.setFetchQueue(&fetchQueue);
- decode.setDecodeQueue(&decodeQueue);
- rename.setDecodeQueue(&decodeQueue);
- rename.setRenameQueue(&renameQueue);
- iew.setRenameQueue(&renameQueue);
- iew.setIEWQueue(&iewQueue);
- commit.setIEWQueue(&iewQueue);
- commit.setRenameQueue(&renameQueue);
-
- commit.setFetchStage(&fetch);
- commit.setIEWStage(&iew);
- rename.setIEWStage(&iew);
- rename.setCommitStage(&commit);
-
-#if !FULL_SYSTEM
- int active_threads = params->workload.size();
-#else
- int active_threads = 1;
-#endif
-
- //Make Sure That this a Valid Architeture
- assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs);
- assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs);
-
- rename.setScoreboard(&scoreboard);
- iew.setScoreboard(&scoreboard);
-
- // Setup the rename map for whichever stages need it.
- PhysRegIndex lreg_idx = 0;
- PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs
-
- for (int tid=0; tid < numThreads; tid++) {
- bool bindRegs = (tid <= active_threads - 1);
-
- commitRenameMap[tid].init(TheISA::NumIntRegs,
- params->numPhysIntRegs,
- lreg_idx, //Index for Logical. Regs
-
- TheISA::NumFloatRegs,
- params->numPhysFloatRegs,
- freg_idx, //Index for Float Regs
-
- TheISA::NumMiscRegs,
-
- TheISA::ZeroReg,
- TheISA::ZeroReg,
-
- tid,
- false);
-
- renameMap[tid].init(TheISA::NumIntRegs,
- params->numPhysIntRegs,
- lreg_idx, //Index for Logical. Regs
-
- TheISA::NumFloatRegs,
- params->numPhysFloatRegs,
- freg_idx, //Index for Float Regs
-
- TheISA::NumMiscRegs,
-
- TheISA::ZeroReg,
- TheISA::ZeroReg,
-
- tid,
- bindRegs);
- }
-
- rename.setRenameMap(renameMap);
- commit.setRenameMap(commitRenameMap);
-
- // Give renameMap & rename stage access to the freeList;
- for (int i=0; i < numThreads; i++) {
- renameMap[i].setFreeList(&freeList);
- }
- rename.setFreeList(&freeList);
-
- // Setup the page table for whichever stages need it.
-#if !FULL_SYSTEM
-// fetch.setPageTable(pTable);
-// iew.setPageTable(pTable);
-#endif
-
- // Setup the ROB for whichever stages need it.
- commit.setROB(&rob);
-
- lastRunningCycle = curTick;
-
- contextSwitch = false;
-}
-
-template <class Impl>
-FullO3CPU<Impl>::~FullO3CPU()
-{
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::fullCPURegStats()
-{
- BaseFullCPU::regStats();
-
- // Register any of the FullCPU's stats here.
- timesIdled
- .name(name() + ".timesIdled")
- .desc("Number of times that the entire CPU went into an idle state and"
- " unscheduled itself")
- .prereq(timesIdled);
-
- idleCycles
- .name(name() + ".idleCycles")
- .desc("Total number of cycles that the CPU has spent unscheduled due "
- "to idling")
- .prereq(idleCycles);
-
- // Number of Instructions simulated
- // --------------------------------
- // Should probably be in Base CPU but need templated
- // MaxThreads so put in here instead
- committedInsts
- .init(numThreads)
- .name(name() + ".committedInsts")
- .desc("Number of Instructions Simulated");
-
- totalCommittedInsts
- .name(name() + ".committedInsts_total")
- .desc("Number of Instructions Simulated");
-
- cpi
- .name(name() + ".cpi")
- .desc("CPI: Cycles Per Instruction")
- .precision(6);
- cpi = simTicks / committedInsts;
-
- totalCpi
- .name(name() + ".cpi_total")
- .desc("CPI: Total CPI of All Threads")
- .precision(6);
- totalCpi = simTicks / totalCommittedInsts;
-
- ipc
- .name(name() + ".ipc")
- .desc("IPC: Instructions Per Cycle")
- .precision(6);
- ipc = committedInsts / simTicks;
-
- totalIpc
- .name(name() + ".ipc_total")
- .desc("IPC: Total IPC of All Threads")
- .precision(6);
- totalIpc = totalCommittedInsts / simTicks;
-
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::tick()
-{
- DPRINTF(FullCPU, "\n\nFullCPU: Ticking main, FullO3CPU.\n");
-
- ++numCycles;
-
-// activity = false;
-
- //Tick each of the stages
- fetch.tick();
-
- decode.tick();
-
- rename.tick();
-
- iew.tick();
-
- commit.tick();
-
-#if !FULL_SYSTEM
- doContextSwitch();
-#endif
-
- // Now advance the time buffers
- timeBuffer.advance();
-
- fetchQueue.advance();
- decodeQueue.advance();
- renameQueue.advance();
- iewQueue.advance();
-
- activityRec.advance();
-
- if (removeInstsThisCycle) {
- cleanUpRemovedInsts();
- }
-
- if (!tickEvent.scheduled()) {
- if (_status == SwitchedOut) {
- // increment stat
- lastRunningCycle = curTick;
- } else if (!activityRec.active()) {
- lastRunningCycle = curTick;
- timesIdled++;
- } else {
- tickEvent.schedule(curTick + cycles(1));
- }
- }
-
-#if !FULL_SYSTEM
- updateThreadPriority();
-#endif
-
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::init()
-{
- if (!deferRegistration) {
- registerExecContexts();
- }
-
- // Set inSyscall so that the CPU doesn't squash when initially
- // setting up registers.
- for (int i = 0; i < number_of_threads; ++i)
- thread[i]->inSyscall = true;
-
- for (int tid=0; tid < number_of_threads; tid++) {
-#if FULL_SYSTEM
- ExecContext *src_xc = execContexts[tid];
-#else
- ExecContext *src_xc = thread[tid]->getXCProxy();
-#endif
- // Threads start in the Suspended State
- if (src_xc->status() != ExecContext::Suspended) {
- continue;
- }
-
-#if FULL_SYSTEM
- TheISA::initCPU(src_xc, src_xc->readCpuId());
-#endif
- }
-
- // Clear inSyscall.
- for (int i = 0; i < number_of_threads; ++i)
- thread[i]->inSyscall = false;
-
- // Initialize stages.
- fetch.initStage();
- iew.initStage();
- rename.initStage();
- commit.initStage();
-
- commit.setThreads(thread);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::insertThread(unsigned tid)
-{
- DPRINTF(FullCPU,"[tid:%i] Initializing thread data");
- // Will change now that the PC and thread state is internal to the CPU
- // and not in the CPUExecContext.
-#if 0
-#if FULL_SYSTEM
- ExecContext *src_xc = system->execContexts[tid];
-#else
- CPUExecContext *src_xc = thread[tid];
-#endif
-
- //Bind Int Regs to Rename Map
- for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
- PhysRegIndex phys_reg = freeList.getIntReg();
-
- renameMap[tid].setEntry(ireg,phys_reg);
- scoreboard.setReg(phys_reg);
- }
-
- //Bind Float Regs to Rename Map
- for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
- PhysRegIndex phys_reg = freeList.getFloatReg();
-
- renameMap[tid].setEntry(freg,phys_reg);
- scoreboard.setReg(phys_reg);
- }
-
- //Copy Thread Data Into RegFile
- this->copyFromXC(tid);
-
- //Set PC/NPC
- regFile.pc[tid] = src_xc->readPC();
- regFile.npc[tid] = src_xc->readNextPC();
-
- src_xc->setStatus(ExecContext::Active);
-
- activateContext(tid,1);
-
- //Reset ROB/IQ/LSQ Entries
- commit.rob->resetEntries();
- iew.resetEntries();
-#endif
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::removeThread(unsigned tid)
-{
- DPRINTF(FullCPU,"[tid:%i] Removing thread data");
-#if 0
- //Unbind Int Regs from Rename Map
- for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
- PhysRegIndex phys_reg = renameMap[tid].lookup(ireg);
-
- scoreboard.unsetReg(phys_reg);
- freeList.addReg(phys_reg);
- }
-
- //Unbind Float Regs from Rename Map
- for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
- PhysRegIndex phys_reg = renameMap[tid].lookup(freg);
-
- scoreboard.unsetReg(phys_reg);
- freeList.addReg(phys_reg);
- }
-
- //Copy Thread Data From RegFile
- /* Fix Me:
- * Do we really need to do this if we are removing a thread
- * in the sense that it's finished (exiting)? If the thread is just
- * being suspended we might...
- */
-// this->copyToXC(tid);
-
- //Squash Throughout Pipeline
- fetch.squash(0,tid);
- decode.squash(tid);
- rename.squash(tid);
-
- assert(iew.ldstQueue.getCount(tid) == 0);
-
- //Reset ROB/IQ/LSQ Entries
- if (activeThreads.size() >= 1) {
- commit.rob->resetEntries();
- iew.resetEntries();
- }
-#endif
-}
-
-
-template <class Impl>
-void
-FullO3CPU<Impl>::activateWhenReady(int tid)
-{
- DPRINTF(FullCPU,"[tid:%i]: Checking if resources are available for incoming"
- "(e.g. PhysRegs/ROB/IQ/LSQ) \n",
- tid);
-
- bool ready = true;
-
- if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) {
- DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
- "Phys. Int. Regs.\n",
- tid);
- ready = false;
- } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) {
- DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
- "Phys. Float. Regs.\n",
- tid);
- ready = false;
- } else if (commit.rob->numFreeEntries() >=
- commit.rob->entryAmount(activeThreads.size() + 1)) {
- DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
- "ROB entries.\n",
- tid);
- ready = false;
- } else if (iew.instQueue.numFreeEntries() >=
- iew.instQueue.entryAmount(activeThreads.size() + 1)) {
- DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
- "IQ entries.\n",
- tid);
- ready = false;
- } else if (iew.ldstQueue.numFreeEntries() >=
- iew.ldstQueue.entryAmount(activeThreads.size() + 1)) {
- DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
- "LSQ entries.\n",
- tid);
- ready = false;
- }
-
- if (ready) {
- insertThread(tid);
-
- contextSwitch = false;
-
- cpuWaitList.remove(tid);
- } else {
- suspendContext(tid);
-
- //blocks fetch
- contextSwitch = true;
-
- //do waitlist
- cpuWaitList.push_back(tid);
- }
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::activateContext(int tid, int delay)
-{
- // Needs to set each stage to running as well.
- list<unsigned>::iterator isActive = find(
- activeThreads.begin(), activeThreads.end(), tid);
-
- if (isActive == activeThreads.end()) {
- //May Need to Re-code this if the delay variable is the
- //delay needed for thread to activate
- DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
- tid);
-
- activeThreads.push_back(tid);
- }
-
- assert(_status == Idle || _status == SwitchedOut);
-
- scheduleTickEvent(delay);
-
- // Be sure to signal that there's some activity so the CPU doesn't
- // deschedule itself.
- activityRec.activity();
- fetch.wakeFromQuiesce();
-
- _status = Running;
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::suspendContext(int tid)
-{
- DPRINTF(FullCPU,"[tid: %i]: Suspended ...\n", tid);
- unscheduleTickEvent();
- _status = Idle;
-/*
- //Remove From Active List, if Active
- list<unsigned>::iterator isActive = find(
- activeThreads.begin(), activeThreads.end(), tid);
-
- if (isActive != activeThreads.end()) {
- DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
- tid);
- activeThreads.erase(isActive);
- }
-*/
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::deallocateContext(int tid)
-{
- DPRINTF(FullCPU,"[tid:%i]: Deallocating ...", tid);
-/*
- //Remove From Active List, if Active
- list<unsigned>::iterator isActive = find(
- activeThreads.begin(), activeThreads.end(), tid);
-
- if (isActive != activeThreads.end()) {
- DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
- tid);
- activeThreads.erase(isActive);
-
- removeThread(tid);
- }
-*/
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::haltContext(int tid)
-{
- DPRINTF(FullCPU,"[tid:%i]: Halted ...", tid);
-/*
- //Remove From Active List, if Active
- list<unsigned>::iterator isActive = find(
- activeThreads.begin(), activeThreads.end(), tid);
-
- if (isActive != activeThreads.end()) {
- DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
- tid);
- activeThreads.erase(isActive);
-
- removeThread(tid);
- }
-*/
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::switchOut(Sampler *_sampler)
-{
- sampler = _sampler;
- switchCount = 0;
- fetch.switchOut();
- decode.switchOut();
- rename.switchOut();
- iew.switchOut();
- commit.switchOut();
-
- // Wake the CPU and record activity so everything can drain out if
- // the CPU is currently idle.
- wakeCPU();
- activityRec.activity();
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::signalSwitched()
-{
- if (++switchCount == NumStages) {
- fetch.doSwitchOut();
- rename.doSwitchOut();
- commit.doSwitchOut();
- instList.clear();
- while (!removeList.empty()) {
- removeList.pop();
- }
-
- if (checker)
- checker->switchOut(sampler);
-
- if (tickEvent.scheduled())
- tickEvent.squash();
- sampler->signalSwitched();
- _status = SwitchedOut;
- }
- assert(switchCount <= 5);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
-{
- // Flush out any old data from the time buffers.
- for (int i = 0; i < 10; ++i) {
- timeBuffer.advance();
- fetchQueue.advance();
- decodeQueue.advance();
- renameQueue.advance();
- iewQueue.advance();
- }
-
- activityRec.reset();
-
- BaseCPU::takeOverFrom(oldCPU);
-
- fetch.takeOverFrom();
- decode.takeOverFrom();
- rename.takeOverFrom();
- iew.takeOverFrom();
- commit.takeOverFrom();
-
- assert(!tickEvent.scheduled());
-
- // @todo: Figure out how to properly select the tid to put onto
- // the active threads list.
- int tid = 0;
-
- list<unsigned>::iterator isActive = find(
- activeThreads.begin(), activeThreads.end(), tid);
-
- if (isActive == activeThreads.end()) {
- //May Need to Re-code this if the delay variable is the delay
- //needed for thread to activate
- DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
- tid);
-
- activeThreads.push_back(tid);
- }
-
- // Set all statuses to active, schedule the CPU's tick event.
- // @todo: Fix up statuses so this is handled properly
- for (int i = 0; i < execContexts.size(); ++i) {
- ExecContext *xc = execContexts[i];
- if (xc->status() == ExecContext::Active && _status != Running) {
- _status = Running;
- tickEvent.schedule(curTick);
- }
- }
- if (!tickEvent.scheduled())
- tickEvent.schedule(curTick);
-}
-
-template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readIntReg(int reg_idx)
-{
- return regFile.readIntReg(reg_idx);
-}
-
-template <class Impl>
-float
-FullO3CPU<Impl>::readFloatRegSingle(int reg_idx)
-{
- return regFile.readFloatRegSingle(reg_idx);
-}
-
-template <class Impl>
-double
-FullO3CPU<Impl>::readFloatRegDouble(int reg_idx)
-{
- return regFile.readFloatRegDouble(reg_idx);
-}
-
-template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readFloatRegInt(int reg_idx)
-{
- return regFile.readFloatRegInt(reg_idx);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val)
-{
- regFile.setIntReg(reg_idx, val);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setFloatRegSingle(int reg_idx, float val)
-{
- regFile.setFloatRegSingle(reg_idx, val);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setFloatRegDouble(int reg_idx, double val)
-{
- regFile.setFloatRegDouble(reg_idx, val);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setFloatRegInt(int reg_idx, uint64_t val)
-{
- regFile.setFloatRegInt(reg_idx, val);
-}
-
-template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readArchIntReg(int reg_idx, unsigned tid)
-{
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
-
- return regFile.readIntReg(phys_reg);
-}
-
-template <class Impl>
-float
-FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid)
-{
- int idx = reg_idx + TheISA::FP_Base_DepTag;
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
-
- return regFile.readFloatRegSingle(phys_reg);
-}
-
-template <class Impl>
-double
-FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid)
-{
- int idx = reg_idx + TheISA::FP_Base_DepTag;
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
-
- return regFile.readFloatRegDouble(phys_reg);
-}
-
-template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid)
-{
- int idx = reg_idx + TheISA::FP_Base_DepTag;
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
-
- return regFile.readFloatRegInt(phys_reg);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid)
-{
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
-
- regFile.setIntReg(phys_reg, val);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid)
-{
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
-
- regFile.setFloatRegSingle(phys_reg, val);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid)
-{
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
-
- regFile.setFloatRegDouble(phys_reg, val);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid)
-{
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
-
- regFile.setFloatRegInt(phys_reg, val);
-}
-
-template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readPC(unsigned tid)
-{
- return commit.readPC(tid);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid)
-{
- commit.setPC(new_PC, tid);
-}
-
-template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readNextPC(unsigned tid)
-{
- return commit.readNextPC(tid);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid)
-{
- commit.setNextPC(val, tid);
-}
-
-template <class Impl>
-typename FullO3CPU<Impl>::ListIt
-FullO3CPU<Impl>::addInst(DynInstPtr &inst)
-{
- instList.push_back(inst);
-
- return --(instList.end());
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::instDone(unsigned tid)
-{
- // Keep an instruction count.
- thread[tid]->numInst++;
- thread[tid]->numInsts++;
- committedInsts[tid]++;
- totalCommittedInsts++;
-
- // Check for instruction-count-based events.
- comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst)
-{
- removeInstsThisCycle = true;
-
- removeList.push(inst->getInstListIt());
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
-{
- DPRINTF(FullCPU, "FullCPU: Removing committed instruction [tid:%i] PC %#x "
- "[sn:%lli]\n",
- inst->threadNumber, inst->readPC(), inst->seqNum);
-
- removeInstsThisCycle = true;
-
- // Remove the front instruction.
- removeList.push(inst->getInstListIt());
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid)
-{
- DPRINTF(FullCPU, "FullCPU: Thread %i: Deleting instructions from instruction"
- " list.\n", tid);
-
- ListIt end_it;
-
- bool rob_empty = false;
-
- if (instList.empty()) {
- return;
- } else if (rob.isEmpty(/*tid*/)) {
- DPRINTF(FullCPU, "FullCPU: ROB is empty, squashing all insts.\n");
- end_it = instList.begin();
- rob_empty = true;
- } else {
- end_it = (rob.readTailInst(tid))->getInstListIt();
- DPRINTF(FullCPU, "FullCPU: ROB is not empty, squashing insts not in ROB.\n");
- }
-
- removeInstsThisCycle = true;
-
- ListIt inst_it = instList.end();
-
- inst_it--;
-
- // Walk through the instruction list, removing any instructions
- // that were inserted after the given instruction iterator, end_it.
- while (inst_it != end_it) {
- assert(!instList.empty());
-
- squashInstIt(inst_it, tid);
-
- inst_it--;
- }
-
- // If the ROB was empty, then we actually need to remove the first
- // instruction as well.
- if (rob_empty) {
- squashInstIt(inst_it, tid);
- }
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num,
- unsigned tid)
-{
- assert(!instList.empty());
-
- removeInstsThisCycle = true;
-
- ListIt inst_iter = instList.end();
-
- inst_iter--;
-
- DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction "
- "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
- tid, seq_num, (*inst_iter)->seqNum);
-
- while ((*inst_iter)->seqNum > seq_num) {
-
- bool break_loop = (inst_iter == instList.begin());
-
- squashInstIt(inst_iter, tid);
-
- inst_iter--;
-
- if (break_loop)
- break;
- }
-}
-
-template <class Impl>
-inline void
-FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid)
-{
- if ((*instIt)->threadNumber == tid) {
- DPRINTF(FullCPU, "FullCPU: Squashing instruction, "
- "[tid:%i] [sn:%lli] PC %#x\n",
- (*instIt)->threadNumber,
- (*instIt)->seqNum,
- (*instIt)->readPC());
-
- // Mark it as squashed.
- (*instIt)->setSquashed();
-
- // @todo: Formulate a consistent method for deleting
- // instructions from the instruction list
- // Remove the instruction from the list.
- removeList.push(instIt);
- }
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::cleanUpRemovedInsts()
-{
- while (!removeList.empty()) {
- DPRINTF(FullCPU, "FullCPU: Removing instruction, "
- "[tid:%i] [sn:%lli] PC %#x\n",
- (*removeList.front())->threadNumber,
- (*removeList.front())->seqNum,
- (*removeList.front())->readPC());
-
- instList.erase(removeList.front());
-
- removeList.pop();
- }
-
- removeInstsThisCycle = false;
-}
-/*
-template <class Impl>
-void
-FullO3CPU<Impl>::removeAllInsts()
-{
- instList.clear();
-}
-*/
-template <class Impl>
-void
-FullO3CPU<Impl>::dumpInsts()
-{
- int num = 0;
-
- ListIt inst_list_it = instList.begin();
-
- cprintf("Dumping Instruction List\n");
-
- while (inst_list_it != instList.end()) {
- cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
- "Squashed:%i\n\n",
- num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber,
- (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
- (*inst_list_it)->isSquashed());
- inst_list_it++;
- ++num;
- }
-}
-/*
-template <class Impl>
-void
-FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
-{
- iew.wakeDependents(inst);
-}
-*/
-template <class Impl>
-void
-FullO3CPU<Impl>::wakeCPU()
-{
- if (activityRec.active() || tickEvent.scheduled()) {
- DPRINTF(Activity, "CPU already running.\n");
- return;
- }
-
- DPRINTF(Activity, "Waking up CPU\n");
-
- idleCycles += (curTick - 1) - lastRunningCycle;
-
- tickEvent.schedule(curTick);
-}
-
-template <class Impl>
-int
-FullO3CPU<Impl>::getFreeTid()
-{
- for (int i=0; i < numThreads; i++) {
- if (!tids[i]) {
- tids[i] = true;
- return i;
- }
- }
-
- return -1;
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::doContextSwitch()
-{
- if (contextSwitch) {
-
- //ADD CODE TO DEACTIVE THREAD HERE (???)
-
- for (int tid=0; tid < cpuWaitList.size(); tid++) {
- activateWhenReady(tid);
- }
-
- if (cpuWaitList.size() == 0)
- contextSwitch = true;
- }
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::updateThreadPriority()
-{
- if (activeThreads.size() > 1)
- {
- //DEFAULT TO ROUND ROBIN SCHEME
- //e.g. Move highest priority to end of thread list
- list<unsigned>::iterator list_begin = activeThreads.begin();
- list<unsigned>::iterator list_end = activeThreads.end();
-
- unsigned high_thread = *list_begin;
-
- activeThreads.erase(list_begin);
-
- activeThreads.push_back(high_thread);
- }
-}
-
-// Forward declaration of FullO3CPU.
-template class FullO3CPU<AlphaSimpleImpl>;
diff --git a/cpu/o3/cpu.hh b/cpu/o3/cpu.hh
deleted file mode 100644
index f4b19bfb3..000000000
--- a/cpu/o3/cpu.hh
+++ /dev/null
@@ -1,540 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_CPU_HH__
-#define __CPU_O3_CPU_HH__
-
-#include <iostream>
-#include <list>
-#include <queue>
-#include <set>
-#include <vector>
-
-#include "base/statistics.hh"
-#include "base/timebuf.hh"
-#include "config/full_system.hh"
-#include "cpu/activity.hh"
-#include "cpu/base.hh"
-#include "cpu/cpu_exec_context.hh"
-#include "cpu/o3/comm.hh"
-#include "cpu/o3/cpu_policy.hh"
-#include "cpu/o3/scoreboard.hh"
-#include "cpu/o3/thread_state.hh"
-#include "sim/process.hh"
-
-template <class>
-class Checker;
-class ExecContext;
-class MemInterface;
-class Process;
-
-class BaseFullCPU : public BaseCPU
-{
- //Stuff that's pretty ISA independent will go here.
- public:
- typedef BaseCPU::Params Params;
-
- BaseFullCPU(Params *params);
-
- void regStats();
-
- protected:
- int cpu_id;
-};
-
-/**
- * FullO3CPU class, has each of the stages (fetch through commit)
- * within it, as well as all of the time buffers between stages. The
- * tick() function for the CPU is defined here.
- */
-template <class Impl>
-class FullO3CPU : public BaseFullCPU
-{
- public:
- // Typedefs from the Impl here.
- typedef typename Impl::CPUPol CPUPolicy;
- typedef typename Impl::Params Params;
- typedef typename Impl::DynInstPtr DynInstPtr;
-
- typedef O3ThreadState<Impl> Thread;
-
- typedef typename std::list<DynInstPtr>::iterator ListIt;
-
- public:
- enum Status {
- Running,
- Idle,
- Halted,
- Blocked,
- SwitchedOut
- };
-
- /** Overall CPU status. */
- Status _status;
-
- private:
- class TickEvent : public Event
- {
- private:
- /** Pointer to the CPU. */
- FullO3CPU<Impl> *cpu;
-
- public:
- /** Constructs a tick event. */
- TickEvent(FullO3CPU<Impl> *c);
-
- /** Processes a tick event, calling tick() on the CPU. */
- void process();
- /** Returns the description of the tick event. */
- const char *description();
- };
-
- /** The tick event used for scheduling CPU ticks. */
- TickEvent tickEvent;
-
- /** Schedule tick event, regardless of its current state. */
- void scheduleTickEvent(int delay)
- {
- if (tickEvent.squashed())
- tickEvent.reschedule(curTick + cycles(delay));
- else if (!tickEvent.scheduled())
- tickEvent.schedule(curTick + cycles(delay));
- }
-
- /** Unschedule tick event, regardless of its current state. */
- void unscheduleTickEvent()
- {
- if (tickEvent.scheduled())
- tickEvent.squash();
- }
-
- public:
- /** Constructs a CPU with the given parameters. */
- FullO3CPU(Params *params);
- /** Destructor. */
- ~FullO3CPU();
-
- /** Registers statistics. */
- void fullCPURegStats();
-
- /** Ticks CPU, calling tick() on each stage, and checking the overall
- * activity to see if the CPU should deschedule itself.
- */
- void tick();
-
- /** Initialize the CPU */
- void init();
-
- /** Setup CPU to insert a thread's context */
- void insertThread(unsigned tid);
-
- /** Remove all of a thread's context from CPU */
- void removeThread(unsigned tid);
-
- /** Count the Total Instructions Committed in the CPU. */
- virtual Counter totalInstructions() const
- {
- Counter total(0);
-
- for (int i=0; i < thread.size(); i++)
- total += thread[i]->numInst;
-
- return total;
- }
-
- /** Add Thread to Active Threads List. */
- void activateContext(int tid, int delay);
-
- /** Remove Thread from Active Threads List */
- void suspendContext(int tid);
-
- /** Remove Thread from Active Threads List &&
- * Remove Thread Context from CPU.
- */
- void deallocateContext(int tid);
-
- /** Remove Thread from Active Threads List &&
- * Remove Thread Context from CPU.
- */
- void haltContext(int tid);
-
- /** Activate a Thread When CPU Resources are Available. */
- void activateWhenReady(int tid);
-
- /** Add or Remove a Thread Context in the CPU. */
- void doContextSwitch();
-
- /** Update The Order In Which We Process Threads. */
- void updateThreadPriority();
-
- /** Executes a syscall on this cycle.
- * ---------------------------------------
- * Note: this is a virtual function. CPU-Specific
- * functionality defined in derived classes
- */
- virtual void syscall(int tid) { panic("Unimplemented!"); }
-
- /** Switches out this CPU. */
- void switchOut(Sampler *sampler);
-
- /** Signals to this CPU that a stage has completed switching out. */
- void signalSwitched();
-
- /** Takes over from another CPU. */
- void takeOverFrom(BaseCPU *oldCPU);
-
- /** Get the current instruction sequence number, and increment it. */
- InstSeqNum getAndIncrementInstSeq()
- { return globalSeqNum++; }
-
-#if FULL_SYSTEM
- /** Check if this address is a valid instruction address. */
- bool validInstAddr(Addr addr) { return true; }
-
- /** Check if this address is a valid data address. */
- bool validDataAddr(Addr addr) { return true; }
-
- /** Get instruction asid. */
- int getInstAsid(unsigned tid)
- { return regFile.miscRegs[tid].getInstAsid(); }
-
- /** Get data asid. */
- int getDataAsid(unsigned tid)
- { return regFile.miscRegs[tid].getDataAsid(); }
-#else
- /** Check if this address is a valid instruction address. */
- bool validInstAddr(Addr addr,unsigned tid)
- { return thread[tid]->validInstAddr(addr); }
-
- /** Check if this address is a valid data address. */
- bool validDataAddr(Addr addr,unsigned tid)
- { return thread[tid]->validDataAddr(addr); }
-
- /** Get instruction asid. */
- int getInstAsid(unsigned tid)
- { return thread[tid]->asid; }
-
- /** Get data asid. */
- int getDataAsid(unsigned tid)
- { return thread[tid]->asid; }
-
-#endif
-
- /** Register accessors. Index refers to the physical register index. */
- uint64_t readIntReg(int reg_idx);
-
- float readFloatRegSingle(int reg_idx);
-
- double readFloatRegDouble(int reg_idx);
-
- uint64_t readFloatRegInt(int reg_idx);
-
- void setIntReg(int reg_idx, uint64_t val);
-
- void setFloatRegSingle(int reg_idx, float val);
-
- void setFloatRegDouble(int reg_idx, double val);
-
- void setFloatRegInt(int reg_idx, uint64_t val);
-
- uint64_t readArchIntReg(int reg_idx, unsigned tid);
-
- float readArchFloatRegSingle(int reg_idx, unsigned tid);
-
- double readArchFloatRegDouble(int reg_idx, unsigned tid);
-
- uint64_t readArchFloatRegInt(int reg_idx, unsigned tid);
-
- /** Architectural register accessors. Looks up in the commit
- * rename table to obtain the true physical index of the
- * architected register first, then accesses that physical
- * register.
- */
- void setArchIntReg(int reg_idx, uint64_t val, unsigned tid);
-
- void setArchFloatRegSingle(int reg_idx, float val, unsigned tid);
-
- void setArchFloatRegDouble(int reg_idx, double val, unsigned tid);
-
- void setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid);
-
- /** Reads the commit PC of a specific thread. */
- uint64_t readPC(unsigned tid);
-
- /** Sets the commit PC of a specific thread. */
- void setPC(Addr new_PC, unsigned tid);
-
- /** Reads the next PC of a specific thread. */
- uint64_t readNextPC(unsigned tid);
-
- /** Sets the next PC of a specific thread. */
- void setNextPC(uint64_t val, unsigned tid);
-
- /** Function to add instruction onto the head of the list of the
- * instructions. Used when new instructions are fetched.
- */
- ListIt addInst(DynInstPtr &inst);
-
- /** Function to tell the CPU that an instruction has completed. */
- void instDone(unsigned tid);
-
- /** Add Instructions to the CPU Remove List*/
- void addToRemoveList(DynInstPtr &inst);
-
- /** Remove an instruction from the front end of the list. There's
- * no restriction on location of the instruction.
- */
- void removeFrontInst(DynInstPtr &inst);
-
- /** Remove all instructions that are not currently in the ROB. */
- void removeInstsNotInROB(unsigned tid);
-
- /** Remove all instructions younger than the given sequence number. */
- void removeInstsUntil(const InstSeqNum &seq_num,unsigned tid);
-
- /** Removes the instruction pointed to by the iterator. */
- inline void squashInstIt(const ListIt &instIt, const unsigned &tid);
-
- /** Cleans up all instructions on the remove list. */
- void cleanUpRemovedInsts();
-
- /** Debug function to print all instructions on the list. */
- void dumpInsts();
-
- public:
- /** List of all the instructions in flight. */
- std::list<DynInstPtr> instList;
-
- /** List of all the instructions that will be removed at the end of this
- * cycle.
- */
- std::queue<ListIt> removeList;
-
-#ifdef DEBUG
- /** Debug structure to keep track of the sequence numbers still in
- * flight.
- */
- std::set<InstSeqNum> snList;
-#endif
-
- /** Records if instructions need to be removed this cycle due to
- * being retired or squashed.
- */
- bool removeInstsThisCycle;
-
- protected:
- /** The fetch stage. */
- typename CPUPolicy::Fetch fetch;
-
- /** The decode stage. */
- typename CPUPolicy::Decode decode;
-
- /** The dispatch stage. */
- typename CPUPolicy::Rename rename;
-
- /** The issue/execute/writeback stages. */
- typename CPUPolicy::IEW iew;
-
- /** The commit stage. */
- typename CPUPolicy::Commit commit;
-
- /** The register file. */
- typename CPUPolicy::RegFile regFile;
-
- /** The free list. */
- typename CPUPolicy::FreeList freeList;
-
- /** The rename map. */
- typename CPUPolicy::RenameMap renameMap[Impl::MaxThreads];
-
- /** The commit rename map. */
- typename CPUPolicy::RenameMap commitRenameMap[Impl::MaxThreads];
-
- /** The re-order buffer. */
- typename CPUPolicy::ROB rob;
-
- /** Active Threads List */
- std::list<unsigned> activeThreads;
-
- /** Integer Register Scoreboard */
- Scoreboard scoreboard;
-
- public:
- /** Enum to give each stage a specific index, so when calling
- * activateStage() or deactivateStage(), they can specify which stage
- * is being activated/deactivated.
- */
- enum StageIdx {
- FetchIdx,
- DecodeIdx,
- RenameIdx,
- IEWIdx,
- CommitIdx,
- NumStages };
-
- /** Typedefs from the Impl to get the structs that each of the
- * time buffers should use.
- */
- typedef typename CPUPolicy::TimeStruct TimeStruct;
-
- typedef typename CPUPolicy::FetchStruct FetchStruct;
-
- typedef typename CPUPolicy::DecodeStruct DecodeStruct;
-
- typedef typename CPUPolicy::RenameStruct RenameStruct;
-
- typedef typename CPUPolicy::IEWStruct IEWStruct;
-
- /** The main time buffer to do backwards communication. */
- TimeBuffer<TimeStruct> timeBuffer;
-
- /** The fetch stage's instruction queue. */
- TimeBuffer<FetchStruct> fetchQueue;
-
- /** The decode stage's instruction queue. */
- TimeBuffer<DecodeStruct> decodeQueue;
-
- /** The rename stage's instruction queue. */
- TimeBuffer<RenameStruct> renameQueue;
-
- /** The IEW stage's instruction queue. */
- TimeBuffer<IEWStruct> iewQueue;
-
- private:
- /** The activity recorder; used to tell if the CPU has any
- * activity remaining or if it can go to idle and deschedule
- * itself.
- */
- ActivityRecorder activityRec;
-
- public:
- /** Records that there was time buffer activity this cycle. */
- void activityThisCycle() { activityRec.activity(); }
-
- /** Changes a stage's status to active within the activity recorder. */
- void activateStage(const StageIdx idx)
- { activityRec.activateStage(idx); }
-
- /** Changes a stage's status to inactive within the activity recorder. */
- void deactivateStage(const StageIdx idx)
- { activityRec.deactivateStage(idx); }
-
- /** Wakes the CPU, rescheduling the CPU if it's not already active. */
- void wakeCPU();
-
- /** Gets a free thread id. Use if thread ids change across system. */
- int getFreeTid();
-
- public:
- /** Returns a pointer to a thread's exec context. */
- ExecContext *xcBase(unsigned tid)
- {
- return thread[tid]->getXCProxy();
- }
-
- /** The global sequence number counter. */
- InstSeqNum globalSeqNum;
-
- /** Pointer to the checker, which can dynamically verify
- * instruction results at run time. This can be set to NULL if it
- * is not being used.
- */
- Checker<DynInstPtr> *checker;
-
-#if FULL_SYSTEM
- /** Pointer to the system. */
- System *system;
-
- /** Pointer to the memory controller. */
- MemoryController *memCtrl;
- /** Pointer to physical memory. */
- PhysicalMemory *physmem;
-#endif
-
- /** Pointer to memory. */
- FunctionalMemory *mem;
-
- /** Pointer to the sampler */
- Sampler *sampler;
-
- /** Counter of how many stages have completed switching out. */
- int switchCount;
-
- /** Pointers to all of the threads in the CPU. */
- std::vector<Thread *> thread;
-
-#if 0
- /** Page table pointer. */
- PageTable *pTable;
-#endif
-
- /** Pointer to the icache interface. */
- MemInterface *icacheInterface;
- /** Pointer to the dcache interface. */
- MemInterface *dcacheInterface;
-
- /** Whether or not the CPU should defer its registration. */
- bool deferRegistration;
-
- /** Is there a context switch pending? */
- bool contextSwitch;
-
- /** Threads Scheduled to Enter CPU */
- std::list<int> cpuWaitList;
-
- /** The cycle that the CPU was last running, used for statistics. */
- Tick lastRunningCycle;
-
- /** Number of Threads CPU can process */
- unsigned numThreads;
-
- /** Mapping for system thread id to cpu id */
- std::map<unsigned,unsigned> threadMap;
-
- /** Available thread ids in the cpu*/
- std::vector<unsigned> tids;
-
- /** Stat for total number of times the CPU is descheduled. */
- Stats::Scalar<> timesIdled;
- /** Stat for total number of cycles the CPU spends descheduled. */
- Stats::Scalar<> idleCycles;
- /** Stat for the number of committed instructions per thread. */
- Stats::Vector<> committedInsts;
- /** Stat for the total number of committed instructions. */
- Stats::Scalar<> totalCommittedInsts;
- /** Stat for the CPI per thread. */
- Stats::Formula cpi;
- /** Stat for the total CPI. */
- Stats::Formula totalCpi;
- /** Stat for the IPC per thread. */
- Stats::Formula ipc;
- /** Stat for the total IPC. */
- Stats::Formula totalIpc;
-};
-
-#endif // __CPU_O3_CPU_HH__
diff --git a/cpu/o3/cpu_policy.hh b/cpu/o3/cpu_policy.hh
deleted file mode 100644
index c30e58389..000000000
--- a/cpu/o3/cpu_policy.hh
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_CPU_POLICY_HH__
-#define __CPU_O3_CPU_POLICY_HH__
-
-#include "cpu/o3/bpred_unit.hh"
-#include "cpu/o3/free_list.hh"
-#include "cpu/o3/inst_queue.hh"
-#include "cpu/o3/lsq.hh"
-#include "cpu/o3/lsq_unit.hh"
-#include "cpu/o3/mem_dep_unit.hh"
-#include "cpu/o3/regfile.hh"
-#include "cpu/o3/rename_map.hh"
-#include "cpu/o3/rob.hh"
-#include "cpu/o3/store_set.hh"
-
-#include "cpu/o3/commit.hh"
-#include "cpu/o3/decode.hh"
-#include "cpu/o3/fetch.hh"
-#include "cpu/o3/iew.hh"
-#include "cpu/o3/rename.hh"
-
-#include "cpu/o3/comm.hh"
-
-/**
- * Struct that defines the key classes to be used by the CPU. All
- * classes use the typedefs defined here to determine what are the
- * classes of the other stages and communication buffers. In order to
- * change a structure such as the IQ, simply change the typedef here
- * to use the desired class instead, and recompile. In order to
- * create a different CPU to be used simultaneously with this one, see
- * the alpha_impl.hh file for instructions.
- */
-template<class Impl>
-struct SimpleCPUPolicy
-{
- /** Typedef for the branch prediction unit (which includes the BP,
- * RAS, and BTB).
- */
- typedef BPredUnit<Impl> BPredUnit;
- /** Typedef for the register file. Most classes assume a unified
- * physical register file.
- */
- typedef PhysRegFile<Impl> RegFile;
- /** Typedef for the freelist of registers. */
- typedef SimpleFreeList FreeList;
- /** Typedef for the rename map. */
- typedef SimpleRenameMap RenameMap;
- /** Typedef for the ROB. */
- typedef ROB<Impl> ROB;
- /** Typedef for the instruction queue/scheduler. */
- typedef InstructionQueue<Impl> IQ;
- /** Typedef for the memory dependence unit. */
- typedef MemDepUnit<StoreSet, Impl> MemDepUnit;
- /** Typedef for the LSQ. */
- typedef LSQ<Impl> LSQ;
- /** Typedef for the thread-specific LSQ units. */
- typedef LSQUnit<Impl> LSQUnit;
-
- /** Typedef for fetch. */
- typedef DefaultFetch<Impl> Fetch;
- /** Typedef for decode. */
- typedef DefaultDecode<Impl> Decode;
- /** Typedef for rename. */
- typedef DefaultRename<Impl> Rename;
- /** Typedef for Issue/Execute/Writeback. */
- typedef DefaultIEW<Impl> IEW;
- /** Typedef for commit. */
- typedef DefaultCommit<Impl> Commit;
-
- /** The struct for communication between fetch and decode. */
- typedef DefaultFetchDefaultDecode<Impl> FetchStruct;
-
- /** The struct for communication between decode and rename. */
- typedef DefaultDecodeDefaultRename<Impl> DecodeStruct;
-
- /** The struct for communication between rename and IEW. */
- typedef DefaultRenameDefaultIEW<Impl> RenameStruct;
-
- /** The struct for communication between IEW and commit. */
- typedef DefaultIEWDefaultCommit<Impl> IEWStruct;
-
- /** The struct for communication within the IEW stage. */
- typedef IssueStruct<Impl> IssueStruct;
-
- /** The struct for all backwards communication. */
- typedef TimeBufStruct<Impl> TimeStruct;
-
-};
-
-#endif //__CPU_O3_CPU_POLICY_HH__
diff --git a/cpu/o3/decode.cc b/cpu/o3/decode.cc
deleted file mode 100644
index b14fbb7a3..000000000
--- a/cpu/o3/decode.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/o3/alpha_dyn_inst.hh"
-#include "cpu/o3/alpha_impl.hh"
-#include "cpu/o3/decode_impl.hh"
-
-template class DefaultDecode<AlphaSimpleImpl>;
diff --git a/cpu/o3/decode.hh b/cpu/o3/decode.hh
deleted file mode 100644
index b336575a8..000000000
--- a/cpu/o3/decode.hh
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_DECODE_HH__
-#define __CPU_O3_DECODE_HH__
-
-#include <queue>
-
-#include "base/statistics.hh"
-#include "base/timebuf.hh"
-
-/**
- * DefaultDecode class handles both single threaded and SMT
- * decode. Its width is specified by the parameters; each cycles it
- * tries to decode that many instructions. Because instructions are
- * actually decoded when the StaticInst is created, this stage does
- * not do much other than check any PC-relative branches.
- */
-template<class Impl>
-class DefaultDecode
-{
- private:
- // Typedefs from the Impl.
- typedef typename Impl::FullCPU FullCPU;
- typedef typename Impl::DynInstPtr DynInstPtr;
- typedef typename Impl::Params Params;
- typedef typename Impl::CPUPol CPUPol;
-
- // Typedefs from the CPU policy.
- typedef typename CPUPol::FetchStruct FetchStruct;
- typedef typename CPUPol::DecodeStruct DecodeStruct;
- typedef typename CPUPol::TimeStruct TimeStruct;
-
- public:
- /** Overall decode stage status. Used to determine if the CPU can
- * deschedule itself due to a lack of activity.
- */
- enum DecodeStatus {
- Active,
- Inactive
- };
-
- /** Individual thread status. */
- enum ThreadStatus {
- Running,
- Idle,
- StartSquash,
- Squashing,
- Blocked,
- Unblocking
- };
-
- private:
- /** Decode status. */
- DecodeStatus _status;
-
- /** Per-thread status. */
- ThreadStatus decodeStatus[Impl::MaxThreads];
-
- public:
- /** DefaultDecode constructor. */
- DefaultDecode(Params *params);
-
- /** Returns the name of decode. */
- std::string name() const;
-
- /** Registers statistics. */
- void regStats();
-
- /** Sets CPU pointer. */
- void setCPU(FullCPU *cpu_ptr);
-
- /** Sets the main backwards communication time buffer pointer. */
- void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
-
- /** Sets pointer to time buffer used to communicate to the next stage. */
- void setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr);
-
- /** Sets pointer to time buffer coming from fetch. */
- void setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr);
-
- /** Sets pointer to list of active threads. */
- void setActiveThreads(std::list<unsigned> *at_ptr);
-
- /** Switches out the decode stage. */
- void switchOut();
-
- /** Takes over from another CPU's thread. */
- void takeOverFrom();
-
- /** Ticks decode, processing all input signals and decoding as many
- * instructions as possible.
- */
- void tick();
-
- /** Determines what to do based on decode's current status.
- * @param status_change decode() sets this variable if there was a status
- * change (ie switching from from blocking to unblocking).
- * @param tid Thread id to decode instructions from.
- */
- void decode(bool &status_change, unsigned tid);
-
- /** Processes instructions from fetch and passes them on to rename.
- * Decoding of instructions actually happens when they are created in
- * fetch, so this function mostly checks if PC-relative branches are
- * correct.
- */
- void decodeInsts(unsigned tid);
-
- private:
- /** Inserts a thread's instructions into the skid buffer, to be decoded
- * once decode unblocks.
- */
- void skidInsert(unsigned tid);
-
- /** Returns if all of the skid buffers are empty. */
- bool skidsEmpty();
-
- /** Updates overall decode status based on all of the threads' statuses. */
- void updateStatus();
-
- /** Separates instructions from fetch into individual lists of instructions
- * sorted by thread.
- */
- void sortInsts();
-
- /** Reads all stall signals from the backwards communication timebuffer. */
- void readStallSignals(unsigned tid);
-
- /** Checks all input signals and updates decode's status appropriately. */
- bool checkSignalsAndUpdate(unsigned tid);
-
- /** Checks all stall signals, and returns if any are true. */
- bool checkStall(unsigned tid) const;
-
- /** Returns if there any instructions from fetch on this cycle. */
- inline bool fetchInstsValid();
-
- /** Switches decode to blocking, and signals back that decode has
- * become blocked.
- * @return Returns true if there is a status change.
- */
- bool block(unsigned tid);
-
- /** Switches decode to unblocking if the skid buffer is empty, and
- * signals back that decode has unblocked.
- * @return Returns true if there is a status change.
- */
- bool unblock(unsigned tid);
-
- /** Squashes if there is a PC-relative branch that was predicted
- * incorrectly. Sends squash information back to fetch.
- */
- void squash(DynInstPtr &inst, unsigned tid);
-
- public:
- /** Squashes due to commit signalling a squash. Changes status to
- * squashing and clears block/unblock signals as needed.
- */
- unsigned squash(unsigned tid);
-
- private:
- // Interfaces to objects outside of decode.
- /** CPU interface. */
- FullCPU *cpu;
-
- /** Time buffer interface. */
- TimeBuffer<TimeStruct> *timeBuffer;
-
- /** Wire to get rename's output from backwards time buffer. */
- typename TimeBuffer<TimeStruct>::wire fromRename;
-
- /** Wire to get iew's information from backwards time buffer. */
- typename TimeBuffer<TimeStruct>::wire fromIEW;
-
- /** Wire to get commit's information from backwards time buffer. */
- typename TimeBuffer<TimeStruct>::wire fromCommit;
-
- /** Wire to write information heading to previous stages. */
- // Might not be the best name as not only fetch will read it.
- typename TimeBuffer<TimeStruct>::wire toFetch;
-
- /** Decode instruction queue. */
- TimeBuffer<DecodeStruct> *decodeQueue;
-
- /** Wire used to write any information heading to rename. */
- typename TimeBuffer<DecodeStruct>::wire toRename;
-
- /** Fetch instruction queue interface. */
- TimeBuffer<FetchStruct> *fetchQueue;
-
- /** Wire to get fetch's output from fetch queue. */
- typename TimeBuffer<FetchStruct>::wire fromFetch;
-
- /** Queue of all instructions coming from fetch this cycle. */
- std::queue<DynInstPtr> insts[Impl::MaxThreads];
-
- /** Skid buffer between fetch and decode. */
- std::queue<DynInstPtr> skidBuffer[Impl::MaxThreads];
-
- /** Variable that tracks if decode has written to the time buffer this
- * cycle. Used to tell CPU if there is activity this cycle.
- */
- bool wroteToTimeBuffer;
-
- /** Source of possible stalls. */
- struct Stalls {
- bool rename;
- bool iew;
- bool commit;
- };
-
- /** Tracks which stages are telling decode to stall. */
- Stalls stalls[Impl::MaxThreads];
-
- /** Rename to decode delay, in ticks. */
- unsigned renameToDecodeDelay;
-
- /** IEW to decode delay, in ticks. */
- unsigned iewToDecodeDelay;
-
- /** Commit to decode delay, in ticks. */
- unsigned commitToDecodeDelay;
-
- /** Fetch to decode delay, in ticks. */
- unsigned fetchToDecodeDelay;
-
- /** The width of decode, in instructions. */
- unsigned decodeWidth;
-
- /** Index of instructions being sent to rename. */
- unsigned toRenameIndex;
-
- /** number of Active Threads*/
- unsigned numThreads;
-
- /** List of active thread ids */
- std::list<unsigned> *activeThreads;
-
- /** Number of branches in flight. */
- unsigned branchCount[Impl::MaxThreads];
-
- /** Maximum size of the skid buffer. */
- unsigned skidBufferMax;
-
- /** Stat for total number of idle cycles. */
- Stats::Scalar<> decodeIdleCycles;
- /** Stat for total number of blocked cycles. */
- Stats::Scalar<> decodeBlockedCycles;
- /** Stat for total number of normal running cycles. */
- Stats::Scalar<> decodeRunCycles;
- /** Stat for total number of unblocking cycles. */
- Stats::Scalar<> decodeUnblockCycles;
- /** Stat for total number of squashing cycles. */
- Stats::Scalar<> decodeSquashCycles;
- /** Stat for number of times a branch is resolved at decode. */
- Stats::Scalar<> decodeBranchResolved;
- /** Stat for number of times a branch mispredict is detected. */
- Stats::Scalar<> decodeBranchMispred;
- /** Stat for number of times decode detected a non-control instruction
- * incorrectly predicted as a branch.
- */
- Stats::Scalar<> decodeControlMispred;
- /** Stat for total number of decoded instructions. */
- Stats::Scalar<> decodeDecodedInsts;
- /** Stat for total number of squashed instructions. */
- Stats::Scalar<> decodeSquashedInsts;
-};
-
-#endif // __CPU_O3_DECODE_HH__
diff --git a/cpu/o3/decode_impl.hh b/cpu/o3/decode_impl.hh
deleted file mode 100644
index 0b686375e..000000000
--- a/cpu/o3/decode_impl.hh
+++ /dev/null
@@ -1,750 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/o3/decode.hh"
-
-using namespace std;
-
-template<class Impl>
-DefaultDecode<Impl>::DefaultDecode(Params *params)
- : renameToDecodeDelay(params->renameToDecodeDelay),
- iewToDecodeDelay(params->iewToDecodeDelay),
- commitToDecodeDelay(params->commitToDecodeDelay),
- fetchToDecodeDelay(params->fetchToDecodeDelay),
- decodeWidth(params->decodeWidth),
- numThreads(params->numberOfThreads)
-{
- _status = Inactive;
-
- // Setup status, make sure stall signals are clear.
- for (int i = 0; i < numThreads; ++i) {
- decodeStatus[i] = Idle;
-
- stalls[i].rename = false;
- stalls[i].iew = false;
- stalls[i].commit = false;
- }
-
- // @todo: Make into a parameter
- skidBufferMax = (fetchToDecodeDelay * params->fetchWidth) + decodeWidth;
-}
-
-template <class Impl>
-std::string
-DefaultDecode<Impl>::name() const
-{
- return cpu->name() + ".decode";
-}
-
-template <class Impl>
-void
-DefaultDecode<Impl>::regStats()
-{
- decodeIdleCycles
- .name(name() + ".DECODE:IdleCycles")
- .desc("Number of cycles decode is idle")
- .prereq(decodeIdleCycles);
- decodeBlockedCycles
- .name(name() + ".DECODE:BlockedCycles")
- .desc("Number of cycles decode is blocked")
- .prereq(decodeBlockedCycles);
- decodeRunCycles
- .name(name() + ".DECODE:RunCycles")
- .desc("Number of cycles decode is running")
- .prereq(decodeRunCycles);
- decodeUnblockCycles
- .name(name() + ".DECODE:UnblockCycles")
- .desc("Number of cycles decode is unblocking")
- .prereq(decodeUnblockCycles);
- decodeSquashCycles
- .name(name() + ".DECODE:SquashCycles")
- .desc("Number of cycles decode is squashing")
- .prereq(decodeSquashCycles);
- decodeBranchResolved
- .name(name() + ".DECODE:BranchResolved")
- .desc("Number of times decode resolved a branch")
- .prereq(decodeBranchResolved);
- decodeBranchMispred
- .name(name() + ".DECODE:BranchMispred")
- .desc("Number of times decode detected a branch misprediction")
- .prereq(decodeBranchMispred);
- decodeControlMispred
- .name(name() + ".DECODE:ControlMispred")
- .desc("Number of times decode detected an instruction incorrectly"
- " predicted as a control")
- .prereq(decodeControlMispred);
- decodeDecodedInsts
- .name(name() + ".DECODE:DecodedInsts")
- .desc("Number of instructions handled by decode")
- .prereq(decodeDecodedInsts);
- decodeSquashedInsts
- .name(name() + ".DECODE:SquashedInsts")
- .desc("Number of squashed instructions handled by decode")
- .prereq(decodeSquashedInsts);
-}
-
-template<class Impl>
-void
-DefaultDecode<Impl>::setCPU(FullCPU *cpu_ptr)
-{
- DPRINTF(Decode, "Setting CPU pointer.\n");
- cpu = cpu_ptr;
-}
-
-template<class Impl>
-void
-DefaultDecode<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
-{
- DPRINTF(Decode, "Setting time buffer pointer.\n");
- timeBuffer = tb_ptr;
-
- // Setup wire to write information back to fetch.
- toFetch = timeBuffer->getWire(0);
-
- // Create wires to get information from proper places in time buffer.
- fromRename = timeBuffer->getWire(-renameToDecodeDelay);
- fromIEW = timeBuffer->getWire(-iewToDecodeDelay);
- fromCommit = timeBuffer->getWire(-commitToDecodeDelay);
-}
-
-template<class Impl>
-void
-DefaultDecode<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
-{
- DPRINTF(Decode, "Setting decode queue pointer.\n");
- decodeQueue = dq_ptr;
-
- // Setup wire to write information to proper place in decode queue.
- toRename = decodeQueue->getWire(0);
-}
-
-template<class Impl>
-void
-DefaultDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
-{
- DPRINTF(Decode, "Setting fetch queue pointer.\n");
- fetchQueue = fq_ptr;
-
- // Setup wire to read information from fetch queue.
- fromFetch = fetchQueue->getWire(-fetchToDecodeDelay);
-}
-
-template<class Impl>
-void
-DefaultDecode<Impl>::setActiveThreads(list<unsigned> *at_ptr)
-{
- DPRINTF(Decode, "Setting active threads list pointer.\n");
- activeThreads = at_ptr;
-}
-
-template <class Impl>
-void
-DefaultDecode<Impl>::switchOut()
-{
- // Decode can immediately switch out.
- cpu->signalSwitched();
-}
-
-template <class Impl>
-void
-DefaultDecode<Impl>::takeOverFrom()
-{
- _status = Inactive;
-
- // Be sure to reset state and clear out any old instructions.
- for (int i = 0; i < numThreads; ++i) {
- decodeStatus[i] = Idle;
-
- stalls[i].rename = false;
- stalls[i].iew = false;
- stalls[i].commit = false;
- while (!insts[i].empty())
- insts[i].pop();
- while (!skidBuffer[i].empty())
- skidBuffer[i].pop();
- branchCount[i] = 0;
- }
- wroteToTimeBuffer = false;
-}
-
-template<class Impl>
-bool
-DefaultDecode<Impl>::checkStall(unsigned tid) const
-{
- bool ret_val = false;
-
- if (stalls[tid].rename) {
- DPRINTF(Decode,"[tid:%i]: Stall fom Rename stage detected.\n", tid);
- ret_val = true;
- } else if (stalls[tid].iew) {
- DPRINTF(Decode,"[tid:%i]: Stall fom IEW stage detected.\n", tid);
- ret_val = true;
- } else if (stalls[tid].commit) {
- DPRINTF(Decode,"[tid:%i]: Stall fom Commit stage detected.\n", tid);
- ret_val = true;
- }
-
- return ret_val;
-}
-
-template<class Impl>
-inline bool
-DefaultDecode<Impl>::fetchInstsValid()
-{
- return fromFetch->size > 0;
-}
-
-template<class Impl>
-bool
-DefaultDecode<Impl>::block(unsigned tid)
-{
- DPRINTF(Decode, "[tid:%u]: Blocking.\n", tid);
-
- // Add the current inputs to the skid buffer so they can be
- // reprocessed when this stage unblocks.
- skidInsert(tid);
-
- // If the decode status is blocked or unblocking then decode has not yet
- // signalled fetch to unblock. In that case, there is no need to tell
- // fetch to block.
- if (decodeStatus[tid] != Blocked) {
- // Set the status to Blocked.
- decodeStatus[tid] = Blocked;
-
- if (decodeStatus[tid] != Unblocking) {
- toFetch->decodeBlock[tid] = true;
- wroteToTimeBuffer = true;
- }
-
- return true;
- }
-
- return false;
-}
-
-template<class Impl>
-bool
-DefaultDecode<Impl>::unblock(unsigned tid)
-{
- // Decode is done unblocking only if the skid buffer is empty.
- if (skidBuffer[tid].empty()) {
- DPRINTF(Decode, "[tid:%u]: Done unblocking.\n", tid);
- toFetch->decodeUnblock[tid] = true;
- wroteToTimeBuffer = true;
-
- decodeStatus[tid] = Running;
- return true;
- }
-
- DPRINTF(Decode, "[tid:%u]: Currently unblocking.\n", tid);
-
- return false;
-}
-
-template<class Impl>
-void
-DefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid)
-{
- DPRINTF(Decode, "[tid:%i]: Squashing due to incorrect branch prediction "
- "detected at decode.\n", tid);
-
- // Send back mispredict information.
- toFetch->decodeInfo[tid].branchMispredict = true;
- toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum;
- toFetch->decodeInfo[tid].predIncorrect = true;
- toFetch->decodeInfo[tid].squash = true;
- toFetch->decodeInfo[tid].nextPC = inst->readNextPC();
- toFetch->decodeInfo[tid].branchTaken =
- inst->readNextPC() != (inst->readPC() + sizeof(TheISA::MachInst));
-
- // Might have to tell fetch to unblock.
- if (decodeStatus[tid] == Blocked ||
- decodeStatus[tid] == Unblocking) {
- toFetch->decodeUnblock[tid] = 1;
- }
-
- // Set status to squashing.
- decodeStatus[tid] = Squashing;
-
- for (int i=0; i<fromFetch->size; i++) {
- if (fromFetch->insts[i]->threadNumber == tid &&
- fromFetch->insts[i]->seqNum > inst->seqNum) {
- fromFetch->insts[i]->squashed = true;
- }
- }
-
- // Clear the instruction list and skid buffer in case they have any
- // insts in them.
- while (!insts[tid].empty()) {
- insts[tid].pop();
- }
-
- while (!skidBuffer[tid].empty()) {
- skidBuffer[tid].pop();
- }
-
- // Squash instructions up until this one
- cpu->removeInstsUntil(inst->seqNum, tid);
-}
-
-template<class Impl>
-unsigned
-DefaultDecode<Impl>::squash(unsigned tid)
-{
- DPRINTF(Decode, "[tid:%i]: Squashing.\n",tid);
-
- if (decodeStatus[tid] == Blocked ||
- decodeStatus[tid] == Unblocking) {
-#if !FULL_SYSTEM
- // In syscall emulation, we can have both a block and a squash due
- // to a syscall in the same cycle. This would cause both signals to
- // be high. This shouldn't happen in full system.
- // @todo: Determine if this still happens.
- if (toFetch->decodeBlock[tid]) {
- toFetch->decodeBlock[tid] = 0;
- } else {
- toFetch->decodeUnblock[tid] = 1;
- }
-#else
- toFetch->decodeUnblock[tid] = 1;
-#endif
- }
-
- // Set status to squashing.
- decodeStatus[tid] = Squashing;
-
- // Go through incoming instructions from fetch and squash them.
- unsigned squash_count = 0;
-
- for (int i=0; i<fromFetch->size; i++) {
- if (fromFetch->insts[i]->threadNumber == tid) {
- fromFetch->insts[i]->squashed = true;
- squash_count++;
- }
- }
-
- // Clear the instruction list and skid buffer in case they have any
- // insts in them.
- while (!insts[tid].empty()) {
- insts[tid].pop();
- }
-
- while (!skidBuffer[tid].empty()) {
- skidBuffer[tid].pop();
- }
-
- return squash_count;
-}
-
-template<class Impl>
-void
-DefaultDecode<Impl>::skidInsert(unsigned tid)
-{
- DynInstPtr inst = NULL;
-
- while (!insts[tid].empty()) {
- inst = insts[tid].front();
-
- insts[tid].pop();
-
- assert(tid == inst->threadNumber);
-
- DPRINTF(Decode,"Inserting [sn:%lli] PC:%#x into decode skidBuffer %i\n",
- inst->seqNum, inst->readPC(), inst->threadNumber);
-
- skidBuffer[tid].push(inst);
- }
-
- // @todo: Eventually need to enforce this by not letting a thread
- // fetch past its skidbuffer
- assert(skidBuffer[tid].size() <= skidBufferMax);
-}
-
-template<class Impl>
-bool
-DefaultDecode<Impl>::skidsEmpty()
-{
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- if (!skidBuffer[*threads++].empty())
- return false;
- }
-
- return true;
-}
-
-template<class Impl>
-void
-DefaultDecode<Impl>::updateStatus()
-{
- bool any_unblocking = false;
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- if (decodeStatus[tid] == Unblocking) {
- any_unblocking = true;
- break;
- }
- }
-
- // Decode will have activity if it's unblocking.
- if (any_unblocking) {
- if (_status == Inactive) {
- _status = Active;
-
- DPRINTF(Activity, "Activating stage.\n");
-
- cpu->activateStage(FullCPU::DecodeIdx);
- }
- } else {
- // If it's not unblocking, then decode will not have any internal
- // activity. Switch it to inactive.
- if (_status == Active) {
- _status = Inactive;
- DPRINTF(Activity, "Deactivating stage.\n");
-
- cpu->deactivateStage(FullCPU::DecodeIdx);
- }
- }
-}
-
-template <class Impl>
-void
-DefaultDecode<Impl>::sortInsts()
-{
- int insts_from_fetch = fromFetch->size;
-#ifdef DEBUG
- for (int i=0; i < numThreads; i++)
- assert(insts[i].empty());
-#endif
- for (int i = 0; i < insts_from_fetch; ++i) {
- insts[fromFetch->insts[i]->threadNumber].push(fromFetch->insts[i]);
- }
-}
-
-template<class Impl>
-void
-DefaultDecode<Impl>::readStallSignals(unsigned tid)
-{
- if (fromRename->renameBlock[tid]) {
- stalls[tid].rename = true;
- }
-
- if (fromRename->renameUnblock[tid]) {
- assert(stalls[tid].rename);
- stalls[tid].rename = false;
- }
-
- if (fromIEW->iewBlock[tid]) {
- stalls[tid].iew = true;
- }
-
- if (fromIEW->iewUnblock[tid]) {
- assert(stalls[tid].iew);
- stalls[tid].iew = false;
- }
-
- if (fromCommit->commitBlock[tid]) {
- stalls[tid].commit = true;
- }
-
- if (fromCommit->commitUnblock[tid]) {
- assert(stalls[tid].commit);
- stalls[tid].commit = false;
- }
-}
-
-template <class Impl>
-bool
-DefaultDecode<Impl>::checkSignalsAndUpdate(unsigned tid)
-{
- // Check if there's a squash signal, squash if there is.
- // Check stall signals, block if necessary.
- // If status was blocked
- // Check if stall conditions have passed
- // if so then go to unblocking
- // If status was Squashing
- // check if squashing is not high. Switch to running this cycle.
-
- // Update the per thread stall statuses.
- readStallSignals(tid);
-
- // Check squash signals from commit.
- if (fromCommit->commitInfo[tid].squash) {
-
- DPRINTF(Decode, "[tid:%u]: Squashing instructions due to squash "
- "from commit.\n", tid);
-
- squash(tid);
-
- return true;
- }
-
- // Check ROB squash signals from commit.
- if (fromCommit->commitInfo[tid].robSquashing) {
- DPRINTF(Decode, "[tid:%]: ROB is still squashing.\n",tid);
-
- // Continue to squash.
- decodeStatus[tid] = Squashing;
-
- return true;
- }
-
- if (checkStall(tid)) {
- return block(tid);
- }
-
- if (decodeStatus[tid] == Blocked) {
- DPRINTF(Decode, "[tid:%u]: Done blocking, switching to unblocking.\n",
- tid);
-
- decodeStatus[tid] = Unblocking;
-
- unblock(tid);
-
- return true;
- }
-
- if (decodeStatus[tid] == Squashing) {
- // Switch status to running if decode isn't being told to block or
- // squash this cycle.
- DPRINTF(Decode, "[tid:%u]: Done squashing, switching to running.\n",
- tid);
-
- decodeStatus[tid] = Running;
-
- return false;
- }
-
- // If we've reached this point, we have not gotten any signals that
- // cause decode to change its status. Decode remains the same as before.
- return false;
-}
-
-template<class Impl>
-void
-DefaultDecode<Impl>::tick()
-{
- wroteToTimeBuffer = false;
-
- bool status_change = false;
-
- toRenameIndex = 0;
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- sortInsts();
-
- //Check stall and squash signals.
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- DPRINTF(Decode,"Processing [tid:%i]\n",tid);
- status_change = checkSignalsAndUpdate(tid) || status_change;
-
- decode(status_change, tid);
- }
-
- if (status_change) {
- updateStatus();
- }
-
- if (wroteToTimeBuffer) {
- DPRINTF(Activity, "Activity this cycle.\n");
-
- cpu->activityThisCycle();
- }
-}
-
-template<class Impl>
-void
-DefaultDecode<Impl>::decode(bool &status_change, unsigned tid)
-{
- // If status is Running or idle,
- // call decodeInsts()
- // If status is Unblocking,
- // buffer any instructions coming from fetch
- // continue trying to empty skid buffer
- // check if stall conditions have passed
-
- if (decodeStatus[tid] == Blocked) {
- ++decodeBlockedCycles;
- } else if (decodeStatus[tid] == Squashing) {
- ++decodeSquashCycles;
- }
-
- // Decode should try to decode as many instructions as its bandwidth
- // will allow, as long as it is not currently blocked.
- if (decodeStatus[tid] == Running ||
- decodeStatus[tid] == Idle) {
- DPRINTF(Decode, "[tid:%u] Not blocked, so attempting to run "
- "stage.\n",tid);
-
- decodeInsts(tid);
- } else if (decodeStatus[tid] == Unblocking) {
- // Make sure that the skid buffer has something in it if the
- // status is unblocking.
- assert(!skidsEmpty());
-
- // If the status was unblocking, then instructions from the skid
- // buffer were used. Remove those instructions and handle
- // the rest of unblocking.
- decodeInsts(tid);
-
- if (fetchInstsValid()) {
- // Add the current inputs to the skid buffer so they can be
- // reprocessed when this stage unblocks.
- skidInsert(tid);
- }
-
- status_change = unblock(tid) || status_change;
- }
-}
-
-template <class Impl>
-void
-DefaultDecode<Impl>::decodeInsts(unsigned tid)
-{
- // Instructions can come either from the skid buffer or the list of
- // instructions coming from fetch, depending on decode's status.
- int insts_available = decodeStatus[tid] == Unblocking ?
- skidBuffer[tid].size() : insts[tid].size();
-
- if (insts_available == 0) {
- DPRINTF(Decode, "[tid:%u] Nothing to do, breaking out"
- " early.\n",tid);
- // Should I change the status to idle?
- ++decodeIdleCycles;
- return;
- } else if (decodeStatus[tid] == Unblocking) {
- DPRINTF(Decode, "[tid:%u] Unblocking, removing insts from skid "
- "buffer.\n",tid);
- ++decodeUnblockCycles;
- } else if (decodeStatus[tid] == Running) {
- ++decodeRunCycles;
- }
-
- DynInstPtr inst;
-
- std::queue<DynInstPtr>
- &insts_to_decode = decodeStatus[tid] == Unblocking ?
- skidBuffer[tid] : insts[tid];
-
- DPRINTF(Decode, "[tid:%u]: Sending instruction to rename.\n",tid);
-
- while (insts_available > 0 && toRenameIndex < decodeWidth) {
- assert(!insts_to_decode.empty());
-
- inst = insts_to_decode.front();
-
- insts_to_decode.pop();
-
- DPRINTF(Decode, "[tid:%u]: Processing instruction [sn:%lli] with "
- "PC %#x\n",
- tid, inst->seqNum, inst->readPC());
-
- if (inst->isSquashed()) {
- DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %#x is "
- "squashed, skipping.\n",
- tid, inst->seqNum, inst->readPC());
-
- ++decodeSquashedInsts;
-
- --insts_available;
-
- continue;
- }
-
- // Also check if instructions have no source registers. Mark
- // them as ready to issue at any time. Not sure if this check
- // should exist here or at a later stage; however it doesn't matter
- // too much for function correctness.
- if (inst->numSrcRegs() == 0) {
- inst->setCanIssue();
- }
-
- // This current instruction is valid, so add it into the decode
- // queue. The next instruction may not be valid, so check to
- // see if branches were predicted correctly.
- toRename->insts[toRenameIndex] = inst;
-
- ++(toRename->size);
- ++toRenameIndex;
- ++decodeDecodedInsts;
- --insts_available;
-
- // Ensure that if it was predicted as a branch, it really is a
- // branch.
- if (inst->predTaken() && !inst->isControl()) {
- panic("Instruction predicted as a branch!");
-
- ++decodeControlMispred;
-
- // Might want to set some sort of boolean and just do
- // a check at the end
- squash(inst, inst->threadNumber);
-
- break;
- }
-
- // Go ahead and compute any PC-relative branches.
- if (inst->isDirectCtrl() && inst->isUncondCtrl()) {
- ++decodeBranchResolved;
- inst->setNextPC(inst->branchTarget());
-
- if (inst->mispredicted()) {
- ++decodeBranchMispred;
-
- // Might want to set some sort of boolean and just do
- // a check at the end
- squash(inst, inst->threadNumber);
- inst->setPredTarg(inst->branchTarget());
-
- break;
- }
- }
- }
-
- // If we didn't process all instructions, then we will need to block
- // and put all those instructions into the skid buffer.
- if (!insts_to_decode.empty()) {
- block(tid);
- }
-
- // Record that decode has written to the time buffer for activity
- // tracking.
- if (toRenameIndex) {
- wroteToTimeBuffer = true;
- }
-}
diff --git a/cpu/o3/dep_graph.hh b/cpu/o3/dep_graph.hh
deleted file mode 100644
index b6c5f1ab1..000000000
--- a/cpu/o3/dep_graph.hh
+++ /dev/null
@@ -1,235 +0,0 @@
-
-#ifndef __CPU_O3_DEP_GRAPH_HH__
-#define __CPU_O3_DEP_GRAPH_HH__
-
-#include "cpu/o3/comm.hh"
-
-/** Node in a linked list. */
-template <class DynInstPtr>
-class DependencyEntry
-{
- public:
- DependencyEntry()
- : inst(NULL), next(NULL)
- { }
-
- DynInstPtr inst;
- //Might want to include data about what arch. register the
- //dependence is waiting on.
- DependencyEntry<DynInstPtr> *next;
-};
-
-/** Array of linked list that maintains the dependencies between
- * producing instructions and consuming instructions. Each linked
- * list represents a single physical register, having the future
- * producer of the register's value, and all consumers waiting on that
- * value on the list. The head node of each linked list represents
- * the producing instruction of that register. Instructions are put
- * on the list upon reaching the IQ, and are removed from the list
- * either when the producer completes, or the instruction is squashed.
-*/
-template <class DynInstPtr>
-class DependencyGraph
-{
- public:
- typedef DependencyEntry<DynInstPtr> DepEntry;
-
- /** Default construction. Must call resize() prior to use. */
- DependencyGraph()
- : numEntries(0), memAllocCounter(0), nodesTraversed(0), nodesRemoved(0)
- { }
-
- /** Resize the dependency graph to have num_entries registers. */
- void resize(int num_entries);
-
- /** Clears all of the linked lists. */
- void reset();
-
- /** Inserts an instruction to be dependent on the given index. */
- void insert(PhysRegIndex idx, DynInstPtr &new_inst);
-
- /** Sets the producing instruction of a given register. */
- void setInst(PhysRegIndex idx, DynInstPtr &new_inst)
- { dependGraph[idx].inst = new_inst; }
-
- /** Clears the producing instruction. */
- void clearInst(PhysRegIndex idx)
- { dependGraph[idx].inst = NULL; }
-
- /** Removes an instruction from a single linked list. */
- void remove(PhysRegIndex idx, DynInstPtr &inst_to_remove);
-
- /** Removes and returns the newest dependent of a specific register. */
- DynInstPtr pop(PhysRegIndex idx);
-
- /** Checks if there are any dependents on a specific register. */
- bool empty(PhysRegIndex idx) { return !dependGraph[idx].next; }
-
- /** Debugging function to dump out the dependency graph.
- */
- void dump();
-
- private:
- /** Array of linked lists. Each linked list is a list of all the
- * instructions that depend upon a given register. The actual
- * register's index is used to index into the graph; ie all
- * instructions in flight that are dependent upon r34 will be
- * in the linked list of dependGraph[34].
- */
- DepEntry *dependGraph;
-
- /** Number of linked lists; identical to the number of registers. */
- int numEntries;
-
- // Debug variable, remove when done testing.
- unsigned memAllocCounter;
-
- public:
- // Debug variable, remove when done testing.
- uint64_t nodesTraversed;
- // Debug variable, remove when done testing.
- uint64_t nodesRemoved;
-};
-
-template <class DynInstPtr>
-void
-DependencyGraph<DynInstPtr>::resize(int num_entries)
-{
- numEntries = num_entries;
- dependGraph = new DepEntry[numEntries];
-}
-
-template <class DynInstPtr>
-void
-DependencyGraph<DynInstPtr>::reset()
-{
- // Clear the dependency graph
- DepEntry *curr;
- DepEntry *prev;
-
- for (int i = 0; i < numEntries; ++i) {
- curr = dependGraph[i].next;
-
- while (curr) {
- memAllocCounter--;
-
- prev = curr;
- curr = prev->next;
- prev->inst = NULL;
-
- delete prev;
- }
-
- if (dependGraph[i].inst) {
- dependGraph[i].inst = NULL;
- }
-
- dependGraph[i].next = NULL;
- }
-}
-
-template <class DynInstPtr>
-void
-DependencyGraph<DynInstPtr>::insert(PhysRegIndex idx, DynInstPtr &new_inst)
-{
- //Add this new, dependent instruction at the head of the dependency
- //chain.
-
- // First create the entry that will be added to the head of the
- // dependency chain.
- DepEntry *new_entry = new DepEntry;
- new_entry->next = dependGraph[idx].next;
- new_entry->inst = new_inst;
-
- // Then actually add it to the chain.
- dependGraph[idx].next = new_entry;
-
- ++memAllocCounter;
-}
-
-
-template <class DynInstPtr>
-void
-DependencyGraph<DynInstPtr>::remove(PhysRegIndex idx,
- DynInstPtr &inst_to_remove)
-{
- DepEntry *prev = &dependGraph[idx];
- DepEntry *curr = dependGraph[idx].next;
-
- // Make sure curr isn't NULL. Because this instruction is being
- // removed from a dependency list, it must have been placed there at
- // an earlier time. The dependency chain should not be empty,
- // unless the instruction dependent upon it is already ready.
- if (curr == NULL) {
- return;
- }
-
- nodesRemoved++;
-
- // Find the instruction to remove within the dependency linked list.
- while (curr->inst != inst_to_remove) {
- prev = curr;
- curr = curr->next;
- nodesTraversed++;
-
- assert(curr != NULL);
- }
-
- // Now remove this instruction from the list.
- prev->next = curr->next;
-
- --memAllocCounter;
-
- // Could push this off to the destructor of DependencyEntry
- curr->inst = NULL;
-
- delete curr;
-}
-
-template <class DynInstPtr>
-DynInstPtr
-DependencyGraph<DynInstPtr>::pop(PhysRegIndex idx)
-{
- DepEntry *node;
- node = dependGraph[idx].next;
- DynInstPtr inst = NULL;
- if (node) {
- inst = node->inst;
- dependGraph[idx].next = node->next;
- node->inst = NULL;
- memAllocCounter--;
- delete node;
- }
- return inst;
-}
-
-template <class DynInstPtr>
-void
-DependencyGraph<DynInstPtr>::dump()
-{
- DepEntry *curr;
-
- for (int i = 0; i < numEntries; ++i)
- {
- curr = &dependGraph[i];
-
- if (curr->inst) {
- cprintf("dependGraph[%i]: producer: %#x [sn:%lli] consumer: ",
- i, curr->inst->readPC(), curr->inst->seqNum);
- } else {
- cprintf("dependGraph[%i]: No producer. consumer: ", i);
- }
-
- while (curr->next != NULL) {
- curr = curr->next;
-
- cprintf("%#x [sn:%lli] ",
- curr->inst->readPC(), curr->inst->seqNum);
- }
-
- cprintf("\n");
- }
- cprintf("memAllocCounter: %i\n", memAllocCounter);
-}
-
-#endif // __CPU_O3_DEP_GRAPH_HH__
diff --git a/cpu/o3/fetch.cc b/cpu/o3/fetch.cc
deleted file mode 100644
index 7959416be..000000000
--- a/cpu/o3/fetch.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/o3/alpha_dyn_inst.hh"
-#include "cpu/o3/alpha_impl.hh"
-#include "cpu/o3/fetch_impl.hh"
-
-template class DefaultFetch<AlphaSimpleImpl>;
diff --git a/cpu/o3/fetch.hh b/cpu/o3/fetch.hh
deleted file mode 100644
index 92a87ab54..000000000
--- a/cpu/o3/fetch.hh
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_FETCH_HH__
-#define __CPU_O3_FETCH_HH__
-
-#include "base/statistics.hh"
-#include "base/timebuf.hh"
-#include "cpu/pc_event.hh"
-#include "mem/mem_interface.hh"
-#include "sim/eventq.hh"
-
-class Sampler;
-
-/**
- * DefaultFetch class handles both single threaded and SMT fetch. Its
- * width is specified by the parameters; each cycle it tries to fetch
- * that many instructions. It supports using a branch predictor to
- * predict direction and targets.
- * It supports the idling functionality of the CPU by indicating to
- * the CPU when it is active and inactive.
- */
-template <class Impl>
-class DefaultFetch
-{
- public:
- /** Typedefs from Impl. */
- typedef typename Impl::CPUPol CPUPol;
- typedef typename Impl::DynInst DynInst;
- typedef typename Impl::DynInstPtr DynInstPtr;
- typedef typename Impl::FullCPU FullCPU;
- typedef typename Impl::Params Params;
-
- /** Typedefs from the CPU policy. */
- typedef typename CPUPol::BPredUnit BPredUnit;
- typedef typename CPUPol::FetchStruct FetchStruct;
- typedef typename CPUPol::TimeStruct TimeStruct;
-
- /** Typedefs from ISA. */
- typedef TheISA::MachInst MachInst;
- typedef TheISA::ExtMachInst ExtMachInst;
-
- public:
- /** Overall fetch status. Used to determine if the CPU can
- * deschedule itsef due to a lack of activity.
- */
- enum FetchStatus {
- Active,
- Inactive
- };
-
- /** Individual thread status. */
- enum ThreadStatus {
- Running,
- Idle,
- Squashing,
- Blocked,
- Fetching,
- TrapPending,
- QuiescePending,
- SwitchOut,
- IcacheMissStall,
- IcacheMissComplete
- };
-
- /** Fetching Policy, Add new policies here.*/
- enum FetchPriority {
- SingleThread,
- RoundRobin,
- Branch,
- IQ,
- LSQ
- };
-
- private:
- /** Fetch status. */
- FetchStatus _status;
-
- /** Per-thread status. */
- ThreadStatus fetchStatus[Impl::MaxThreads];
-
- /** Fetch policy. */
- FetchPriority fetchPolicy;
-
- /** List that has the threads organized by priority. */
- std::list<unsigned> priorityList;
-
- public:
- class CacheCompletionEvent : public Event
- {
- private:
- MemReqPtr req;
- /** Pointer to fetch. */
- DefaultFetch *fetch;
- /** Thread id. */
-// unsigned threadId;
-
- public:
- /** Constructs a cache completion event, which tells fetch when the
- * cache miss is complete.
- */
- CacheCompletionEvent(MemReqPtr &_req, DefaultFetch *_fetch);
-
- /** Processes cache completion event. */
- virtual void process();
- /** Returns the description of the cache completion event. */
- virtual const char *description();
- };
-
- public:
- /** DefaultFetch constructor. */
- DefaultFetch(Params *params);
-
- /** Returns the name of fetch. */
- std::string name() const;
-
- /** Registers statistics. */
- void regStats();
-
- /** Sets CPU pointer. */
- void setCPU(FullCPU *cpu_ptr);
-
- /** Sets the main backwards communication time buffer pointer. */
- void setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer);
-
- /** Sets pointer to list of active threads. */
- void setActiveThreads(std::list<unsigned> *at_ptr);
-
- /** Sets pointer to time buffer used to communicate to the next stage. */
- void setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr);
-
- /** Sets pointer to page table. */
-// void setPageTable(PageTable *pt_ptr);
-
- /** Initialize stage. */
- void initStage();
-
- /** Processes cache completion event. */
- void processCacheCompletion(MemReqPtr &req);
-
- /** Begins the switch out of the fetch stage. */
- void switchOut();
-
- /** Completes the switch out of the fetch stage. */
- void doSwitchOut();
-
- /** Takes over from another CPU's thread. */
- void takeOverFrom();
-
- /** Checks if the fetch stage is switched out. */
- bool isSwitchedOut() { return switchedOut; }
-
- /** Tells fetch to wake up from a quiesce instruction. */
- void wakeFromQuiesce();
-
- private:
- /** Changes the status of this stage to active, and indicates this
- * to the CPU.
- */
- inline void switchToActive();
-
- /** Changes the status of this stage to inactive, and indicates
- * this to the CPU.
- */
- inline void switchToInactive();
-
- /**
- * Looks up in the branch predictor to see if the next PC should be
- * either next PC+=MachInst or a branch target.
- * @param next_PC Next PC variable passed in by reference. It is
- * expected to be set to the current PC; it will be updated with what
- * the next PC will be.
- * @return Whether or not a branch was predicted as taken.
- */
- bool lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC);
-
- /**
- * Fetches the cache line that contains fetch_PC. Returns any
- * fault that happened. Puts the data into the class variable
- * cacheData.
- * @param fetch_PC The PC address that is being fetched from.
- * @param ret_fault The fault reference that will be set to the result of
- * the icache access.
- * @param tid Thread id.
- * @return Any fault that occured.
- */
- bool fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid);
-
- /** Squashes a specific thread and resets the PC. */
- inline void doSquash(const Addr &new_PC, unsigned tid);
-
- /** Squashes a specific thread and resets the PC. Also tells the CPU to
- * remove any instructions between fetch and decode that should be sqaushed.
- */
- void squashFromDecode(const Addr &new_PC, const InstSeqNum &seq_num,
- unsigned tid);
-
- /** Checks if a thread is stalled. */
- bool checkStall(unsigned tid) const;
-
- /** Updates overall fetch stage status; to be called at the end of each
- * cycle. */
- FetchStatus updateFetchStatus();
-
- public:
- /** Squashes a specific thread and resets the PC. Also tells the CPU to
- * remove any instructions that are not in the ROB. The source of this
- * squash should be the commit stage.
- */
- void squash(const Addr &new_PC, unsigned tid);
-
- /** Ticks the fetch stage, processing all inputs signals and fetching
- * as many instructions as possible.
- */
- void tick();
-
- /** Checks all input signals and updates the status as necessary.
- * @return: Returns if the status has changed due to input signals.
- */
- bool checkSignalsAndUpdate(unsigned tid);
-
- /** Does the actual fetching of instructions and passing them on to the
- * next stage.
- * @param status_change fetch() sets this variable if there was a status
- * change (ie switching to IcacheMissStall).
- */
- void fetch(bool &status_change);
-
- /** Align a PC to the start of an I-cache block. */
- Addr icacheBlockAlignPC(Addr addr)
- {
- addr = TheISA::realPCToFetchPC(addr);
- return (addr & ~(cacheBlkMask));
- }
-
- private:
- /** Returns the appropriate thread to fetch, given the fetch policy. */
- int getFetchingThread(FetchPriority &fetch_priority);
-
- /** Returns the appropriate thread to fetch using a round robin policy. */
- int roundRobin();
-
- /** Returns the appropriate thread to fetch using the IQ count policy. */
- int iqCount();
-
- /** Returns the appropriate thread to fetch using the LSQ count policy. */
- int lsqCount();
-
- /** Returns the appropriate thread to fetch using the branch count policy. */
- int branchCount();
-
- private:
- /** Pointer to the FullCPU. */
- FullCPU *cpu;
-
- /** Time buffer interface. */
- TimeBuffer<TimeStruct> *timeBuffer;
-
- /** Wire to get decode's information from backwards time buffer. */
- typename TimeBuffer<TimeStruct>::wire fromDecode;
-
- /** Wire to get rename's information from backwards time buffer. */
- typename TimeBuffer<TimeStruct>::wire fromRename;
-
- /** Wire to get iew's information from backwards time buffer. */
- typename TimeBuffer<TimeStruct>::wire fromIEW;
-
- /** Wire to get commit's information from backwards time buffer. */
- typename TimeBuffer<TimeStruct>::wire fromCommit;
-
- /** Internal fetch instruction queue. */
- TimeBuffer<FetchStruct> *fetchQueue;
-
- //Might be annoying how this name is different than the queue.
- /** Wire used to write any information heading to decode. */
- typename TimeBuffer<FetchStruct>::wire toDecode;
-
- /** Icache interface. */
- MemInterface *icacheInterface;
-
- /** BPredUnit. */
- BPredUnit branchPred;
-
- /** Per-thread fetch PC. */
- Addr PC[Impl::MaxThreads];
-
- /** Per-thread next PC. */
- Addr nextPC[Impl::MaxThreads];
-
- /** Memory request used to access cache. */
- MemReqPtr memReq[Impl::MaxThreads];
-
- /** Variable that tracks if fetch has written to the time buffer this
- * cycle. Used to tell CPU if there is activity this cycle.
- */
- bool wroteToTimeBuffer;
-
- /** Tracks how many instructions has been fetched this cycle. */
- int numInst;
-
- /** Source of possible stalls. */
- struct Stalls {
- bool decode;
- bool rename;
- bool iew;
- bool commit;
- };
-
- /** Tracks which stages are telling fetch to stall. */
- Stalls stalls[Impl::MaxThreads];
-
- /** Decode to fetch delay, in ticks. */
- unsigned decodeToFetchDelay;
-
- /** Rename to fetch delay, in ticks. */
- unsigned renameToFetchDelay;
-
- /** IEW to fetch delay, in ticks. */
- unsigned iewToFetchDelay;
-
- /** Commit to fetch delay, in ticks. */
- unsigned commitToFetchDelay;
-
- /** The width of fetch in instructions. */
- unsigned fetchWidth;
-
- /** Cache block size. */
- int cacheBlkSize;
-
- /** Mask to get a cache block's address. */
- Addr cacheBlkMask;
-
- /** The cache line being fetched. */
- uint8_t *cacheData[Impl::MaxThreads];
-
- /** Size of instructions. */
- int instSize;
-
- /** Icache stall statistics. */
- Counter lastIcacheStall[Impl::MaxThreads];
-
- /** List of Active Threads */
- std::list<unsigned> *activeThreads;
-
- /** Number of threads. */
- unsigned numThreads;
-
- /** Number of threads that are actively fetching. */
- unsigned numFetchingThreads;
-
- /** Thread ID being fetched. */
- int threadFetched;
-
- /** Checks if there is an interrupt pending. If there is, fetch
- * must stop once it is not fetching PAL instructions.
- */
- bool interruptPending;
-
- /** Records if fetch is switched out. */
- bool switchedOut;
-
-#if !FULL_SYSTEM
- /** Page table pointer. */
-// PageTable *pTable;
-#endif
-
- // @todo: Consider making these vectors and tracking on a per thread basis.
- /** Stat for total number of cycles stalled due to an icache miss. */
- Stats::Scalar<> icacheStallCycles;
- /** Stat for total number of fetched instructions. */
- Stats::Scalar<> fetchedInsts;
- Stats::Scalar<> fetchedBranches;
- /** Stat for total number of predicted branches. */
- Stats::Scalar<> predictedBranches;
- /** Stat for total number of cycles spent fetching. */
- Stats::Scalar<> fetchCycles;
- /** Stat for total number of cycles spent squashing. */
- Stats::Scalar<> fetchSquashCycles;
- /** Stat for total number of cycles spent blocked due to other stages in
- * the pipeline.
- */
- Stats::Scalar<> fetchIdleCycles;
- /** Total number of cycles spent blocked. */
- Stats::Scalar<> fetchBlockedCycles;
- /** Total number of cycles spent in any other state. */
- Stats::Scalar<> fetchMiscStallCycles;
- /** Stat for total number of fetched cache lines. */
- Stats::Scalar<> fetchedCacheLines;
- /** Total number of outstanding icache accesses that were dropped
- * due to a squash.
- */
- Stats::Scalar<> fetchIcacheSquashes;
- /** Distribution of number of instructions fetched each cycle. */
- Stats::Distribution<> fetchNisnDist;
- /** Rate of how often fetch was idle. */
- Stats::Formula idleRate;
- /** Number of branch fetches per cycle. */
- Stats::Formula branchRate;
- /** Number of instruction fetched per cycle. */
- Stats::Formula fetchRate;
-};
-
-#endif //__CPU_O3_FETCH_HH__
diff --git a/cpu/o3/fetch_impl.hh b/cpu/o3/fetch_impl.hh
deleted file mode 100644
index a309bd49a..000000000
--- a/cpu/o3/fetch_impl.hh
+++ /dev/null
@@ -1,1221 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "arch/isa_traits.hh"
-#include "cpu/exetrace.hh"
-#include "cpu/o3/fetch.hh"
-#include "mem/base_mem.hh"
-#include "mem/mem_interface.hh"
-#include "mem/mem_req.hh"
-#include "sim/byteswap.hh"
-#include "sim/root.hh"
-
-#if FULL_SYSTEM
-#include "arch/tlb.hh"
-#include "arch/vtophys.hh"
-#include "base/remote_gdb.hh"
-#include "mem/functional/memory_control.hh"
-#include "mem/functional/physical.hh"
-#include "sim/system.hh"
-#else // !FULL_SYSTEM
-#include "mem/functional/functional.hh"
-#endif // FULL_SYSTEM
-
-#include <algorithm>
-
-using namespace std;
-
-template<class Impl>
-DefaultFetch<Impl>::CacheCompletionEvent::CacheCompletionEvent(MemReqPtr &_req,
- DefaultFetch *_fetch)
- : Event(&mainEventQueue, Delayed_Writeback_Pri),
- req(_req),
- fetch(_fetch)
-{
- this->setFlags(Event::AutoDelete);
-}
-
-template<class Impl>
-void
-DefaultFetch<Impl>::CacheCompletionEvent::process()
-{
- fetch->processCacheCompletion(req);
-}
-
-template<class Impl>
-const char *
-DefaultFetch<Impl>::CacheCompletionEvent::description()
-{
- return "DefaultFetch cache completion event";
-}
-
-template<class Impl>
-DefaultFetch<Impl>::DefaultFetch(Params *params)
- : icacheInterface(params->icacheInterface),
- branchPred(params),
- decodeToFetchDelay(params->decodeToFetchDelay),
- renameToFetchDelay(params->renameToFetchDelay),
- iewToFetchDelay(params->iewToFetchDelay),
- commitToFetchDelay(params->commitToFetchDelay),
- fetchWidth(params->fetchWidth),
- numThreads(params->numberOfThreads),
- numFetchingThreads(params->smtNumFetchingThreads),
- interruptPending(false)
-{
- if (numThreads > Impl::MaxThreads)
- fatal("numThreads is not a valid value\n");
-
- DPRINTF(Fetch, "Fetch constructor called\n");
-
- // Set fetch stage's status to inactive.
- _status = Inactive;
-
- string policy = params->smtFetchPolicy;
-
- // Convert string to lowercase
- std::transform(policy.begin(), policy.end(), policy.begin(),
- (int(*)(int)) tolower);
-
- // Figure out fetch policy
- if (policy == "singlethread") {
- fetchPolicy = SingleThread;
- } else if (policy == "roundrobin") {
- fetchPolicy = RoundRobin;
- DPRINTF(Fetch, "Fetch policy set to Round Robin\n");
- } else if (policy == "branch") {
- fetchPolicy = Branch;
- DPRINTF(Fetch, "Fetch policy set to Branch Count\n");
- } else if (policy == "iqcount") {
- fetchPolicy = IQ;
- DPRINTF(Fetch, "Fetch policy set to IQ count\n");
- } else if (policy == "lsqcount") {
- fetchPolicy = LSQ;
- DPRINTF(Fetch, "Fetch policy set to LSQ count\n");
- } else {
- fatal("Invalid Fetch Policy. Options Are: {SingleThread,"
- " RoundRobin,LSQcount,IQcount}\n");
- }
-
- // Size of cache block.
- cacheBlkSize = icacheInterface ? icacheInterface->getBlockSize() : 64;
-
- // Create mask to get rid of offset bits.
- cacheBlkMask = (cacheBlkSize - 1);
-
- for (int tid=0; tid < numThreads; tid++) {
-
- fetchStatus[tid] = Running;
-
- priorityList.push_back(tid);
-
- // Create a new memory request.
- memReq[tid] = NULL;
-
- // Create space to store a cache line.
- cacheData[tid] = new uint8_t[cacheBlkSize];
-
- stalls[tid].decode = 0;
- stalls[tid].rename = 0;
- stalls[tid].iew = 0;
- stalls[tid].commit = 0;
- }
-
- // Get the size of an instruction.
- instSize = sizeof(MachInst);
-}
-
-template <class Impl>
-std::string
-DefaultFetch<Impl>::name() const
-{
- return cpu->name() + ".fetch";
-}
-
-template <class Impl>
-void
-DefaultFetch<Impl>::regStats()
-{
- icacheStallCycles
- .name(name() + ".icacheStallCycles")
- .desc("Number of cycles fetch is stalled on an Icache miss")
- .prereq(icacheStallCycles);
-
- fetchedInsts
- .name(name() + ".Insts")
- .desc("Number of instructions fetch has processed")
- .prereq(fetchedInsts);
-
- fetchedBranches
- .name(name() + ".Branches")
- .desc("Number of branches that fetch encountered")
- .prereq(fetchedBranches);
-
- predictedBranches
- .name(name() + ".predictedBranches")
- .desc("Number of branches that fetch has predicted taken")
- .prereq(predictedBranches);
-
- fetchCycles
- .name(name() + ".Cycles")
- .desc("Number of cycles fetch has run and was not squashing or"
- " blocked")
- .prereq(fetchCycles);
-
- fetchSquashCycles
- .name(name() + ".SquashCycles")
- .desc("Number of cycles fetch has spent squashing")
- .prereq(fetchSquashCycles);
-
- fetchIdleCycles
- .name(name() + ".IdleCycles")
- .desc("Number of cycles fetch was idle")
- .prereq(fetchIdleCycles);
-
- fetchBlockedCycles
- .name(name() + ".BlockedCycles")
- .desc("Number of cycles fetch has spent blocked")
- .prereq(fetchBlockedCycles);
-
- fetchedCacheLines
- .name(name() + ".CacheLines")
- .desc("Number of cache lines fetched")
- .prereq(fetchedCacheLines);
-
- fetchMiscStallCycles
- .name(name() + ".MiscStallCycles")
- .desc("Number of cycles fetch has spent waiting on interrupts, or "
- "bad addresses, or out of MSHRs")
- .prereq(fetchMiscStallCycles);
-
- fetchIcacheSquashes
- .name(name() + ".IcacheSquashes")
- .desc("Number of outstanding Icache misses that were squashed")
- .prereq(fetchIcacheSquashes);
-
- fetchNisnDist
- .init(/* base value */ 0,
- /* last value */ fetchWidth,
- /* bucket size */ 1)
- .name(name() + ".rateDist")
- .desc("Number of instructions fetched each cycle (Total)")
- .flags(Stats::pdf);
-
- idleRate
- .name(name() + ".idleRate")
- .desc("Percent of cycles fetch was idle")
- .prereq(idleRate);
- idleRate = fetchIdleCycles * 100 / cpu->numCycles;
-
- branchRate
- .name(name() + ".branchRate")
- .desc("Number of branch fetches per cycle")
- .flags(Stats::total);
- branchRate = fetchedBranches / cpu->numCycles;
-
- fetchRate
- .name(name() + ".rate")
- .desc("Number of inst fetches per cycle")
- .flags(Stats::total);
- fetchRate = fetchedInsts / cpu->numCycles;
-
- branchPred.regStats();
-}
-
-template<class Impl>
-void
-DefaultFetch<Impl>::setCPU(FullCPU *cpu_ptr)
-{
- DPRINTF(Fetch, "Setting the CPU pointer.\n");
- cpu = cpu_ptr;
-
- // Fetch needs to start fetching instructions at the very beginning,
- // so it must start up in active state.
- switchToActive();
-}
-
-template<class Impl>
-void
-DefaultFetch<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer)
-{
- DPRINTF(Fetch, "Setting the time buffer pointer.\n");
- timeBuffer = time_buffer;
-
- // Create wires to get information from proper places in time buffer.
- fromDecode = timeBuffer->getWire(-decodeToFetchDelay);
- fromRename = timeBuffer->getWire(-renameToFetchDelay);
- fromIEW = timeBuffer->getWire(-iewToFetchDelay);
- fromCommit = timeBuffer->getWire(-commitToFetchDelay);
-}
-
-template<class Impl>
-void
-DefaultFetch<Impl>::setActiveThreads(list<unsigned> *at_ptr)
-{
- DPRINTF(Fetch, "Setting active threads list pointer.\n");
- activeThreads = at_ptr;
-}
-
-template<class Impl>
-void
-DefaultFetch<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
-{
- DPRINTF(Fetch, "Setting the fetch queue pointer.\n");
- fetchQueue = fq_ptr;
-
- // Create wire to write information to proper place in fetch queue.
- toDecode = fetchQueue->getWire(0);
-}
-
-#if 0
-template<class Impl>
-void
-DefaultFetch<Impl>::setPageTable(PageTable *pt_ptr)
-{
- DPRINTF(Fetch, "Setting the page table pointer.\n");
-#if !FULL_SYSTEM
- pTable = pt_ptr;
-#endif
-}
-#endif
-
-template<class Impl>
-void
-DefaultFetch<Impl>::initStage()
-{
- // Setup PC and nextPC with initial state.
- for (int tid = 0; tid < numThreads; tid++) {
- PC[tid] = cpu->readPC(tid);
- nextPC[tid] = cpu->readNextPC(tid);
- }
-}
-
-template<class Impl>
-void
-DefaultFetch<Impl>::processCacheCompletion(MemReqPtr &req)
-{
- unsigned tid = req->thread_num;
-
- DPRINTF(Fetch, "[tid:%u] Waking up from cache miss.\n",tid);
-
- // Only change the status if it's still waiting on the icache access
- // to return.
- if (fetchStatus[tid] != IcacheMissStall ||
- req != memReq[tid] ||
- isSwitchedOut()) {
- ++fetchIcacheSquashes;
- return;
- }
-
- // Wake up the CPU (if it went to sleep and was waiting on this completion
- // event).
- cpu->wakeCPU();
-
- DPRINTF(Activity, "[tid:%u] Activating fetch due to cache completion\n",
- tid);
-
- switchToActive();
-
- // Only switch to IcacheMissComplete if we're not stalled as well.
- if (checkStall(tid)) {
- fetchStatus[tid] = Blocked;
- } else {
- fetchStatus[tid] = IcacheMissComplete;
- }
-
-// memcpy(cacheData[tid], memReq[tid]->data, memReq[tid]->size);
-
- // Reset the mem req to NULL.
- memReq[tid] = NULL;
-}
-
-template <class Impl>
-void
-DefaultFetch<Impl>::switchOut()
-{
- // Fetch is ready to switch out at any time.
- switchedOut = true;
- cpu->signalSwitched();
-}
-
-template <class Impl>
-void
-DefaultFetch<Impl>::doSwitchOut()
-{
- // Branch predictor needs to have its state cleared.
- branchPred.switchOut();
-}
-
-template <class Impl>
-void
-DefaultFetch<Impl>::takeOverFrom()
-{
- // Reset all state
- for (int i = 0; i < Impl::MaxThreads; ++i) {
- stalls[i].decode = 0;
- stalls[i].rename = 0;
- stalls[i].iew = 0;
- stalls[i].commit = 0;
- PC[i] = cpu->readPC(i);
- nextPC[i] = cpu->readNextPC(i);
- fetchStatus[i] = Running;
- }
- numInst = 0;
- wroteToTimeBuffer = false;
- _status = Inactive;
- switchedOut = false;
- branchPred.takeOverFrom();
-}
-
-template <class Impl>
-void
-DefaultFetch<Impl>::wakeFromQuiesce()
-{
- DPRINTF(Fetch, "Waking up from quiesce\n");
- // Hopefully this is safe
- // @todo: Allow other threads to wake from quiesce.
- fetchStatus[0] = Running;
-}
-
-template <class Impl>
-inline void
-DefaultFetch<Impl>::switchToActive()
-{
- if (_status == Inactive) {
- DPRINTF(Activity, "Activating stage.\n");
-
- cpu->activateStage(FullCPU::FetchIdx);
-
- _status = Active;
- }
-}
-
-template <class Impl>
-inline void
-DefaultFetch<Impl>::switchToInactive()
-{
- if (_status == Active) {
- DPRINTF(Activity, "Deactivating stage.\n");
-
- cpu->deactivateStage(FullCPU::FetchIdx);
-
- _status = Inactive;
- }
-}
-
-template <class Impl>
-bool
-DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC)
-{
- // Do branch prediction check here.
- // A bit of a misnomer...next_PC is actually the current PC until
- // this function updates it.
- bool predict_taken;
-
- if (!inst->isControl()) {
- next_PC = next_PC + instSize;
- inst->setPredTarg(next_PC);
- return false;
- }
-
- predict_taken = branchPred.predict(inst, next_PC, inst->threadNumber);
-
- ++fetchedBranches;
-
- if (predict_taken) {
- ++predictedBranches;
- }
-
- return predict_taken;
-}
-
-template <class Impl>
-bool
-DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid)
-{
- Fault fault = NoFault;
-
-#if FULL_SYSTEM
- // Flag to say whether or not address is physical addr.
- unsigned flags = cpu->inPalMode(fetch_PC) ? PHYSICAL : 0;
-#else
- unsigned flags = 0;
-#endif // FULL_SYSTEM
-
- if (interruptPending && flags == 0 || switchedOut) {
- // Hold off fetch from getting new instructions while an interrupt
- // is pending.
- return false;
- }
-
- // Align the fetch PC so it's at the start of a cache block.
- fetch_PC = icacheBlockAlignPC(fetch_PC);
-
- // Setup the memReq to do a read of the first instruction's address.
- // Set the appropriate read size and flags as well.
- memReq[tid] = new MemReq();
-
- memReq[tid]->asid = tid;
- memReq[tid]->thread_num = tid;
- memReq[tid]->data = new uint8_t[64];
- memReq[tid]->xc = cpu->xcBase(tid);
- memReq[tid]->cmd = Read;
- memReq[tid]->reset(fetch_PC, cacheBlkSize, flags);
-
- // Translate the instruction request.
-//#if FULL_SYSTEM
- fault = cpu->translateInstReq(memReq[tid]);
-//#else
-// fault = pTable->translate(memReq[tid]);
-//#endif
-
- // In the case of faults, the fetch stage may need to stall and wait
- // for the ITB miss to be handled.
-
- // If translation was successful, attempt to read the first
- // instruction.
- if (fault == NoFault) {
-#if FULL_SYSTEM
- if (cpu->system->memctrl->badaddr(memReq[tid]->paddr) ||
- memReq[tid]->flags & UNCACHEABLE) {
- DPRINTF(Fetch, "Fetch: Bad address %#x (hopefully on a "
- "misspeculating path)!",
- memReq[tid]->paddr);
- ret_fault = TheISA::genMachineCheckFault();
- return false;
- }
-#endif
-
- DPRINTF(Fetch, "Fetch: Doing instruction read.\n");
- fault = cpu->mem->read(memReq[tid], cacheData[tid]);
- // This read may change when the mem interface changes.
-
- // Now do the timing access to see whether or not the instruction
- // exists within the cache.
- if (icacheInterface && !icacheInterface->isBlocked()) {
- DPRINTF(Fetch, "Doing cache access.\n");
-
- memReq[tid]->completionEvent = NULL;
-
- memReq[tid]->time = curTick;
-
- MemAccessResult result = icacheInterface->access(memReq[tid]);
-
- fetchedCacheLines++;
-
- // If the cache missed, then schedule an event to wake
- // up this stage once the cache miss completes.
- // @todo: Possibly allow for longer than 1 cycle cache hits.
- if (result != MA_HIT && icacheInterface->doEvents()) {
-
- memReq[tid]->completionEvent =
- new CacheCompletionEvent(memReq[tid], this);
-
- lastIcacheStall[tid] = curTick;
-
- DPRINTF(Activity, "[tid:%i]: Activity: Stalling due to I-cache "
- "miss.\n", tid);
-
- fetchStatus[tid] = IcacheMissStall;
- } else {
- DPRINTF(Fetch, "[tid:%i]: I-Cache hit. Doing Instruction "
- "read.\n", tid);
-
-// memcpy(cacheData[tid], memReq[tid]->data, memReq[tid]->size);
- }
- } else {
- DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid);
- ret_fault = NoFault;
- return false;
- }
- }
-
- ret_fault = fault;
- return true;
-}
-
-template <class Impl>
-inline void
-DefaultFetch<Impl>::doSquash(const Addr &new_PC, unsigned tid)
-{
- DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %#x.\n",
- tid, new_PC);
-
- PC[tid] = new_PC;
- nextPC[tid] = new_PC + instSize;
-
- // Clear the icache miss if it's outstanding.
- if (fetchStatus[tid] == IcacheMissStall && icacheInterface) {
- DPRINTF(Fetch, "[tid:%i]: Squashing outstanding Icache miss.\n",
- tid);
- memReq[tid] = NULL;
- }
-
- fetchStatus[tid] = Squashing;
-
- ++fetchSquashCycles;
-}
-
-template<class Impl>
-void
-DefaultFetch<Impl>::squashFromDecode(const Addr &new_PC,
- const InstSeqNum &seq_num,
- unsigned tid)
-{
- DPRINTF(Fetch, "[tid:%i]: Squashing from decode.\n",tid);
-
- doSquash(new_PC, tid);
-
- // Tell the CPU to remove any instructions that are in flight between
- // fetch and decode.
- cpu->removeInstsUntil(seq_num, tid);
-}
-
-template<class Impl>
-bool
-DefaultFetch<Impl>::checkStall(unsigned tid) const
-{
- bool ret_val = false;
-
- if (cpu->contextSwitch) {
- DPRINTF(Fetch,"[tid:%i]: Stalling for a context switch.\n",tid);
- ret_val = true;
- } else if (stalls[tid].decode) {
- DPRINTF(Fetch,"[tid:%i]: Stall from Decode stage detected.\n",tid);
- ret_val = true;
- } else if (stalls[tid].rename) {
- DPRINTF(Fetch,"[tid:%i]: Stall from Rename stage detected.\n",tid);
- ret_val = true;
- } else if (stalls[tid].iew) {
- DPRINTF(Fetch,"[tid:%i]: Stall from IEW stage detected.\n",tid);
- ret_val = true;
- } else if (stalls[tid].commit) {
- DPRINTF(Fetch,"[tid:%i]: Stall from Commit stage detected.\n",tid);
- ret_val = true;
- }
-
- return ret_val;
-}
-
-template<class Impl>
-typename DefaultFetch<Impl>::FetchStatus
-DefaultFetch<Impl>::updateFetchStatus()
-{
- //Check Running
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
-
- unsigned tid = *threads++;
-
- if (fetchStatus[tid] == Running ||
- fetchStatus[tid] == Squashing ||
- fetchStatus[tid] == IcacheMissComplete) {
-
- if (_status == Inactive) {
- DPRINTF(Activity, "[tid:%i]: Activating stage.\n",tid);
-
- if (fetchStatus[tid] == IcacheMissComplete) {
- DPRINTF(Activity, "[tid:%i]: Activating fetch due to cache"
- "completion\n",tid);
- }
-
- cpu->activateStage(FullCPU::FetchIdx);
- }
-
- return Active;
- }
- }
-
- // Stage is switching from active to inactive, notify CPU of it.
- if (_status == Active) {
- DPRINTF(Activity, "Deactivating stage.\n");
-
- cpu->deactivateStage(FullCPU::FetchIdx);
- }
-
- return Inactive;
-}
-
-template <class Impl>
-void
-DefaultFetch<Impl>::squash(const Addr &new_PC, unsigned tid)
-{
- DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n",tid);
-
- doSquash(new_PC, tid);
-
- // Tell the CPU to remove any instructions that are not in the ROB.
- cpu->removeInstsNotInROB(tid);
-}
-
-template <class Impl>
-void
-DefaultFetch<Impl>::tick()
-{
- list<unsigned>::iterator threads = (*activeThreads).begin();
- bool status_change = false;
-
- wroteToTimeBuffer = false;
-
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- // Check the signals for each thread to determine the proper status
- // for each thread.
- bool updated_status = checkSignalsAndUpdate(tid);
- status_change = status_change || updated_status;
- }
-
- DPRINTF(Fetch, "Running stage.\n");
-
- // Reset the number of the instruction we're fetching.
- numInst = 0;
-
- if (fromCommit->commitInfo[0].interruptPending) {
- interruptPending = true;
- }
- if (fromCommit->commitInfo[0].clearInterrupt) {
- interruptPending = false;
- }
-
- for (threadFetched = 0; threadFetched < numFetchingThreads;
- threadFetched++) {
- // Fetch each of the actively fetching threads.
- fetch(status_change);
- }
-
- // Record number of instructions fetched this cycle for distribution.
- fetchNisnDist.sample(numInst);
-
- if (status_change) {
- // Change the fetch stage status if there was a status change.
- _status = updateFetchStatus();
- }
-
- // If there was activity this cycle, inform the CPU of it.
- if (wroteToTimeBuffer || cpu->contextSwitch) {
- DPRINTF(Activity, "Activity this cycle.\n");
-
- cpu->activityThisCycle();
- }
-}
-
-template <class Impl>
-bool
-DefaultFetch<Impl>::checkSignalsAndUpdate(unsigned tid)
-{
- // Update the per thread stall statuses.
- if (fromDecode->decodeBlock[tid]) {
- stalls[tid].decode = true;
- }
-
- if (fromDecode->decodeUnblock[tid]) {
- assert(stalls[tid].decode);
- assert(!fromDecode->decodeBlock[tid]);
- stalls[tid].decode = false;
- }
-
- if (fromRename->renameBlock[tid]) {
- stalls[tid].rename = true;
- }
-
- if (fromRename->renameUnblock[tid]) {
- assert(stalls[tid].rename);
- assert(!fromRename->renameBlock[tid]);
- stalls[tid].rename = false;
- }
-
- if (fromIEW->iewBlock[tid]) {
- stalls[tid].iew = true;
- }
-
- if (fromIEW->iewUnblock[tid]) {
- assert(stalls[tid].iew);
- assert(!fromIEW->iewBlock[tid]);
- stalls[tid].iew = false;
- }
-
- if (fromCommit->commitBlock[tid]) {
- stalls[tid].commit = true;
- }
-
- if (fromCommit->commitUnblock[tid]) {
- assert(stalls[tid].commit);
- assert(!fromCommit->commitBlock[tid]);
- stalls[tid].commit = false;
- }
-
- // Check squash signals from commit.
- if (fromCommit->commitInfo[tid].squash) {
-
- DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash "
- "from commit.\n",tid);
-
- // In any case, squash.
- squash(fromCommit->commitInfo[tid].nextPC,tid);
-
- // Also check if there's a mispredict that happened.
- if (fromCommit->commitInfo[tid].branchMispredict) {
- branchPred.squash(fromCommit->commitInfo[tid].doneSeqNum,
- fromCommit->commitInfo[tid].nextPC,
- fromCommit->commitInfo[tid].branchTaken,
- tid);
- } else {
- branchPred.squash(fromCommit->commitInfo[tid].doneSeqNum,
- tid);
- }
-
- return true;
- } else if (fromCommit->commitInfo[tid].doneSeqNum) {
- // Update the branch predictor if it wasn't a squashed instruction
- // that was broadcasted.
- branchPred.update(fromCommit->commitInfo[tid].doneSeqNum, tid);
- }
-
- // Check ROB squash signals from commit.
- if (fromCommit->commitInfo[tid].robSquashing) {
- DPRINTF(Fetch, "[tid:%u]: ROB is still squashing Thread %u.\n", tid);
-
- // Continue to squash.
- fetchStatus[tid] = Squashing;
-
- return true;
- }
-
- // Check squash signals from decode.
- if (fromDecode->decodeInfo[tid].squash) {
- DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash "
- "from decode.\n",tid);
-
- // Update the branch predictor.
- if (fromDecode->decodeInfo[tid].branchMispredict) {
- branchPred.squash(fromDecode->decodeInfo[tid].doneSeqNum,
- fromDecode->decodeInfo[tid].nextPC,
- fromDecode->decodeInfo[tid].branchTaken,
- tid);
- } else {
- branchPred.squash(fromDecode->decodeInfo[tid].doneSeqNum,
- tid);
- }
-
- if (fetchStatus[tid] != Squashing) {
- // Squash unless we're already squashing
- squashFromDecode(fromDecode->decodeInfo[tid].nextPC,
- fromDecode->decodeInfo[tid].doneSeqNum,
- tid);
-
- return true;
- }
- }
-
- if (fetchStatus[tid] != IcacheMissStall && checkStall(tid)) {
- DPRINTF(Fetch, "[tid:%i]: Setting to blocked\n",tid);
-
- fetchStatus[tid] = Blocked;
-
- return true;
- }
-
- if (fetchStatus[tid] == Blocked ||
- fetchStatus[tid] == Squashing) {
- // Switch status to running if fetch isn't being told to block or
- // squash this cycle.
- DPRINTF(Fetch, "[tid:%i]: Done squashing, switching to running.\n",
- tid);
-
- fetchStatus[tid] = Running;
-
- return true;
- }
-
- // If we've reached this point, we have not gotten any signals that
- // cause fetch to change its status. Fetch remains the same as before.
- return false;
-}
-
-template<class Impl>
-void
-DefaultFetch<Impl>::fetch(bool &status_change)
-{
- //////////////////////////////////////////
- // Start actual fetch
- //////////////////////////////////////////
- int tid = getFetchingThread(fetchPolicy);
-
- if (tid == -1) {
- DPRINTF(Fetch,"There are no more threads available to fetch from.\n");
-
- // Breaks looping condition in tick()
- threadFetched = numFetchingThreads;
- return;
- }
-
- // The current PC.
- Addr &fetch_PC = PC[tid];
-
- // Fault code for memory access.
- Fault fault = NoFault;
-
- // If returning from the delay of a cache miss, then update the status
- // to running, otherwise do the cache access. Possibly move this up
- // to tick() function.
- if (fetchStatus[tid] == IcacheMissComplete) {
- DPRINTF(Fetch, "[tid:%i]: Icache miss is complete.\n",
- tid);
-
- fetchStatus[tid] = Running;
- status_change = true;
- } else if (fetchStatus[tid] == Running) {
- DPRINTF(Fetch, "[tid:%i]: Attempting to translate and read "
- "instruction, starting at PC %08p.\n",
- tid, fetch_PC);
-
- bool fetch_success = fetchCacheLine(fetch_PC, fault, tid);
- if (!fetch_success) {
- ++fetchMiscStallCycles;
- return;
- }
- } else {
- if (fetchStatus[tid] == Idle) {
- ++fetchIdleCycles;
- } else if (fetchStatus[tid] == Blocked) {
- ++fetchBlockedCycles;
- } else if (fetchStatus[tid] == Squashing) {
- ++fetchSquashCycles;
- } else if (fetchStatus[tid] == IcacheMissStall) {
- ++icacheStallCycles;
- }
-
- // Status is Idle, Squashing, Blocked, or IcacheMissStall, so
- // fetch should do nothing.
- return;
- }
-
- ++fetchCycles;
-
- // If we had a stall due to an icache miss, then return.
- if (fetchStatus[tid] == IcacheMissStall) {
- ++icacheStallCycles;
- status_change = true;
- return;
- }
-
- Addr next_PC = fetch_PC;
- InstSeqNum inst_seq;
- MachInst inst;
- ExtMachInst ext_inst;
- // @todo: Fix this hack.
- unsigned offset = (fetch_PC & cacheBlkMask) & ~3;
-
- if (fault == NoFault) {
- // If the read of the first instruction was successful, then grab the
- // instructions from the rest of the cache line and put them into the
- // queue heading to decode.
-
- DPRINTF(Fetch, "[tid:%i]: Adding instructions to queue to "
- "decode.\n",tid);
-
- // Need to keep track of whether or not a predicted branch
- // ended this fetch block.
- bool predicted_branch = false;
-
- for (;
- offset < cacheBlkSize &&
- numInst < fetchWidth &&
- !predicted_branch;
- ++numInst) {
-
- // Get a sequence number.
- inst_seq = cpu->getAndIncrementInstSeq();
-
- // Make sure this is a valid index.
- assert(offset <= cacheBlkSize - instSize);
-
- // Get the instruction from the array of the cache line.
- inst = gtoh(*reinterpret_cast<MachInst *>
- (&cacheData[tid][offset]));
-
- ext_inst = TheISA::makeExtMI(inst, fetch_PC);
-
- // Create a new DynInst from the instruction fetched.
- DynInstPtr instruction = new DynInst(ext_inst, fetch_PC,
- next_PC,
- inst_seq, cpu);
- instruction->setThread(tid);
-
- instruction->setASID(tid);
-
- instruction->setState(cpu->thread[tid]);
-
- DPRINTF(Fetch, "[tid:%i]: Instruction PC %#x created "
- "[sn:%lli]\n",
- tid, instruction->readPC(), inst_seq);
-
- DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n",
- tid, instruction->staticInst->disassemble(fetch_PC));
-
- instruction->traceData =
- Trace::getInstRecord(curTick, cpu->xcBase(tid), cpu,
- instruction->staticInst,
- instruction->readPC(),tid);
-
- predicted_branch = lookupAndUpdateNextPC(instruction, next_PC);
-
- // Add instruction to the CPU's list of instructions.
- instruction->setInstListIt(cpu->addInst(instruction));
-
- // Write the instruction to the first slot in the queue
- // that heads to decode.
- toDecode->insts[numInst] = instruction;
-
- toDecode->size++;
-
- // Increment stat of fetched instructions.
- ++fetchedInsts;
-
- // Move to the next instruction, unless we have a branch.
- fetch_PC = next_PC;
-
- if (instruction->isQuiesce()) {
- warn("%lli: Quiesce instruction encountered, halting fetch!",
- curTick);
- fetchStatus[tid] = QuiescePending;
- ++numInst;
- status_change = true;
- break;
- }
-
- offset+= instSize;
- }
- }
-
- if (numInst > 0) {
- wroteToTimeBuffer = true;
- }
-
- // Now that fetching is completed, update the PC to signify what the next
- // cycle will be.
- if (fault == NoFault) {
- DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n",tid, next_PC);
-
- PC[tid] = next_PC;
- nextPC[tid] = next_PC + instSize;
- } else {
- // We shouldn't be in an icache miss and also have a fault (an ITB
- // miss)
- if (fetchStatus[tid] == IcacheMissStall) {
- panic("Fetch should have exited prior to this!");
- }
-
- // Send the fault to commit. This thread will not do anything
- // until commit handles the fault. The only other way it can
- // wake up is if a squash comes along and changes the PC.
-#if FULL_SYSTEM
- assert(numInst != fetchWidth);
- // Get a sequence number.
- inst_seq = cpu->getAndIncrementInstSeq();
- // We will use a nop in order to carry the fault.
- ext_inst = TheISA::NoopMachInst;
-
- // Create a new DynInst from the dummy nop.
- DynInstPtr instruction = new DynInst(ext_inst, fetch_PC,
- next_PC,
- inst_seq, cpu);
- instruction->setPredTarg(next_PC + instSize);
- instruction->setThread(tid);
-
- instruction->setASID(tid);
-
- instruction->setState(cpu->thread[tid]);
-
- instruction->traceData = NULL;
-
- instruction->setInstListIt(cpu->addInst(instruction));
-
- instruction->fault = fault;
-
- toDecode->insts[numInst] = instruction;
- toDecode->size++;
-
- DPRINTF(Fetch, "[tid:%i]: Blocked, need to handle the trap.\n",tid);
-
- fetchStatus[tid] = TrapPending;
- status_change = true;
-
- warn("%lli fault (%d) detected @ PC %08p", curTick, fault, PC[tid]);
-#else // !FULL_SYSTEM
- fatal("fault (%d) detected @ PC %08p", fault, PC[tid]);
-#endif // FULL_SYSTEM
- }
-}
-
-
-///////////////////////////////////////
-// //
-// SMT FETCH POLICY MAINTAINED HERE //
-// //
-///////////////////////////////////////
-template<class Impl>
-int
-DefaultFetch<Impl>::getFetchingThread(FetchPriority &fetch_priority)
-{
- if (numThreads > 1) {
- switch (fetch_priority) {
-
- case SingleThread:
- return 0;
-
- case RoundRobin:
- return roundRobin();
-
- case IQ:
- return iqCount();
-
- case LSQ:
- return lsqCount();
-
- case Branch:
- return branchCount();
-
- default:
- return -1;
- }
- } else {
- int tid = *((*activeThreads).begin());
-
- if (fetchStatus[tid] == Running ||
- fetchStatus[tid] == IcacheMissComplete ||
- fetchStatus[tid] == Idle) {
- return tid;
- } else {
- return -1;
- }
- }
-
-}
-
-
-template<class Impl>
-int
-DefaultFetch<Impl>::roundRobin()
-{
- list<unsigned>::iterator pri_iter = priorityList.begin();
- list<unsigned>::iterator end = priorityList.end();
-
- int high_pri;
-
- while (pri_iter != end) {
- high_pri = *pri_iter;
-
- assert(high_pri <= numThreads);
-
- if (fetchStatus[high_pri] == Running ||
- fetchStatus[high_pri] == IcacheMissComplete ||
- fetchStatus[high_pri] == Idle) {
-
- priorityList.erase(pri_iter);
- priorityList.push_back(high_pri);
-
- return high_pri;
- }
-
- pri_iter++;
- }
-
- return -1;
-}
-
-template<class Impl>
-int
-DefaultFetch<Impl>::iqCount()
-{
- priority_queue<unsigned> PQ;
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- PQ.push(fromIEW->iewInfo[tid].iqCount);
- }
-
- while (!PQ.empty()) {
-
- unsigned high_pri = PQ.top();
-
- if (fetchStatus[high_pri] == Running ||
- fetchStatus[high_pri] == IcacheMissComplete ||
- fetchStatus[high_pri] == Idle)
- return high_pri;
- else
- PQ.pop();
-
- }
-
- return -1;
-}
-
-template<class Impl>
-int
-DefaultFetch<Impl>::lsqCount()
-{
- priority_queue<unsigned> PQ;
-
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- PQ.push(fromIEW->iewInfo[tid].ldstqCount);
- }
-
- while (!PQ.empty()) {
-
- unsigned high_pri = PQ.top();
-
- if (fetchStatus[high_pri] == Running ||
- fetchStatus[high_pri] == IcacheMissComplete ||
- fetchStatus[high_pri] == Idle)
- return high_pri;
- else
- PQ.pop();
-
- }
-
- return -1;
-}
-
-template<class Impl>
-int
-DefaultFetch<Impl>::branchCount()
-{
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- return *threads;
-}
diff --git a/cpu/o3/free_list.cc b/cpu/o3/free_list.cc
deleted file mode 100644
index bd0f4f034..000000000
--- a/cpu/o3/free_list.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "base/trace.hh"
-
-#include "cpu/o3/free_list.hh"
-
-SimpleFreeList::SimpleFreeList(unsigned activeThreads,
- unsigned _numLogicalIntRegs,
- unsigned _numPhysicalIntRegs,
- unsigned _numLogicalFloatRegs,
- unsigned _numPhysicalFloatRegs)
- : numLogicalIntRegs(_numLogicalIntRegs),
- numPhysicalIntRegs(_numPhysicalIntRegs),
- numLogicalFloatRegs(_numLogicalFloatRegs),
- numPhysicalFloatRegs(_numPhysicalFloatRegs),
- numPhysicalRegs(numPhysicalIntRegs + numPhysicalFloatRegs)
-{
- DPRINTF(FreeList, "Creating new free list object.\n");
-
- // Put all of the extra physical registers onto the free list. This
- // means excluding all of the base logical registers.
- for (PhysRegIndex i = numLogicalIntRegs * activeThreads;
- i < numPhysicalIntRegs; ++i)
- {
- freeIntRegs.push(i);
- }
-
- // Put all of the extra physical registers onto the free list. This
- // means excluding all of the base logical registers. Because the
- // float registers' indices start where the physical registers end,
- // some math must be done to determine where the free registers start.
- PhysRegIndex i = numPhysicalIntRegs + (numLogicalFloatRegs * activeThreads);
-
- for ( ; i < numPhysicalRegs; ++i)
- {
- freeFloatRegs.push(i);
- }
-}
-
-std::string
-SimpleFreeList::name() const
-{
- return "cpu.freelist";
-}
diff --git a/cpu/o3/free_list.hh b/cpu/o3/free_list.hh
deleted file mode 100644
index 29e84cd44..000000000
--- a/cpu/o3/free_list.hh
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_FREE_LIST_HH__
-#define __CPU_O3_FREE_LIST_HH__
-
-#include <iostream>
-#include <queue>
-
-#include "arch/isa_traits.hh"
-#include "base/trace.hh"
-#include "base/traceflags.hh"
-#include "cpu/o3/comm.hh"
-
-/**
- * FreeList class that simply holds the list of free integer and floating
- * point registers. Can request for a free register of either type, and
- * also send back free registers of either type. This is a very simple
- * class, but it should be sufficient for most implementations. Like all
- * other classes, it assumes that the indices for the floating point
- * registers starts after the integer registers end. Hence the variable
- * numPhysicalIntRegs is logically equivalent to the baseFP dependency.
- * Note that while this most likely should be called FreeList, the name
- * "FreeList" is used in a typedef within the CPU Policy, and therefore no
- * class can be named simply "FreeList".
- * @todo: Give a better name to the base FP dependency.
- */
-class SimpleFreeList
-{
- private:
- /** The list of free integer registers. */
- std::queue<PhysRegIndex> freeIntRegs;
-
- /** The list of free floating point registers. */
- std::queue<PhysRegIndex> freeFloatRegs;
-
- /** Number of logical integer registers. */
- int numLogicalIntRegs;
-
- /** Number of physical integer registers. */
- int numPhysicalIntRegs;
-
- /** Number of logical floating point registers. */
- int numLogicalFloatRegs;
-
- /** Number of physical floating point registers. */
- int numPhysicalFloatRegs;
-
- /** Total number of physical registers. */
- int numPhysicalRegs;
-
- public:
- /** Constructs a free list.
- * @param activeThreads Number of active threads.
- * @param _numLogicalIntRegs Number of logical integer registers.
- * @param _numPhysicalIntRegs Number of physical integer registers.
- * @param _numLogicalFloatRegs Number of logical fp registers.
- * @param _numPhysicalFloatRegs Number of physical fp registers.
- */
- SimpleFreeList(unsigned activeThreads,
- unsigned _numLogicalIntRegs,
- unsigned _numPhysicalIntRegs,
- unsigned _numLogicalFloatRegs,
- unsigned _numPhysicalFloatRegs);
-
- /** Gives the name of the freelist. */
- std::string name() const;
-
- /** Gets a free integer register. */
- inline PhysRegIndex getIntReg();
-
- /** Gets a free fp register. */
- inline PhysRegIndex getFloatReg();
-
- /** Adds a register back to the free list. */
- inline void addReg(PhysRegIndex freed_reg);
-
- /** Adds an integer register back to the free list. */
- inline void addIntReg(PhysRegIndex freed_reg);
-
- /** Adds a fp register back to the free list. */
- inline void addFloatReg(PhysRegIndex freed_reg);
-
- /** Checks if there are any free integer registers. */
- bool hasFreeIntRegs()
- { return !freeIntRegs.empty(); }
-
- /** Checks if there are any free fp registers. */
- bool hasFreeFloatRegs()
- { return !freeFloatRegs.empty(); }
-
- /** Returns the number of free integer registers. */
- int numFreeIntRegs()
- { return freeIntRegs.size(); }
-
- /** Returns the number of free fp registers. */
- int numFreeFloatRegs()
- { return freeFloatRegs.size(); }
-};
-
-inline PhysRegIndex
-SimpleFreeList::getIntReg()
-{
- DPRINTF(FreeList, "Trying to get free integer register.\n");
-
- if (freeIntRegs.empty()) {
- panic("No free integer registers!");
- }
-
- PhysRegIndex free_reg = freeIntRegs.front();
-
- freeIntRegs.pop();
-
- return(free_reg);
-}
-
-inline PhysRegIndex
-SimpleFreeList::getFloatReg()
-{
- DPRINTF(FreeList, "Trying to get free float register.\n");
-
- if (freeFloatRegs.empty()) {
- panic("No free integer registers!");
- }
-
- PhysRegIndex free_reg = freeFloatRegs.front();
-
- freeFloatRegs.pop();
-
- return(free_reg);
-}
-
-inline void
-SimpleFreeList::addReg(PhysRegIndex freed_reg)
-{
- DPRINTF(FreeList,"Freeing register %i.\n", freed_reg);
- //Might want to add in a check for whether or not this register is
- //already in there. A bit vector or something similar would be useful.
- if (freed_reg < numPhysicalIntRegs) {
- if (freed_reg != TheISA::ZeroReg)
- freeIntRegs.push(freed_reg);
- } else if (freed_reg < numPhysicalRegs) {
- if (freed_reg != (TheISA::ZeroReg + numPhysicalIntRegs))
- freeFloatRegs.push(freed_reg);
- }
-}
-
-inline void
-SimpleFreeList::addIntReg(PhysRegIndex freed_reg)
-{
- DPRINTF(FreeList,"Freeing int register %i.\n", freed_reg);
-
- freeIntRegs.push(freed_reg);
-}
-
-inline void
-SimpleFreeList::addFloatReg(PhysRegIndex freed_reg)
-{
- DPRINTF(FreeList,"Freeing float register %i.\n", freed_reg);
-
- freeFloatRegs.push(freed_reg);
-}
-
-#endif // __CPU_O3_FREE_LIST_HH__
diff --git a/cpu/o3/fu_pool.cc b/cpu/o3/fu_pool.cc
deleted file mode 100644
index b28b5d37f..000000000
--- a/cpu/o3/fu_pool.cc
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sstream>
-
-#include "cpu/o3/fu_pool.hh"
-#include "encumbered/cpu/full/fu_pool.hh"
-#include "sim/builder.hh"
-
-using namespace std;
-
-////////////////////////////////////////////////////////////////////////////
-//
-// A pool of function units
-//
-
-inline void
-FUPool::FUIdxQueue::addFU(int fu_idx)
-{
- funcUnitsIdx.push_back(fu_idx);
- ++size;
-}
-
-inline int
-FUPool::FUIdxQueue::getFU()
-{
- int retval = funcUnitsIdx[idx++];
-
- if (idx == size)
- idx = 0;
-
- return retval;
-}
-
-FUPool::~FUPool()
-{
- fuListIterator i = funcUnits.begin();
- fuListIterator end = funcUnits.end();
- for (; i != end; ++i)
- delete *i;
-}
-
-
-// Constructor
-FUPool::FUPool(string name, vector<FUDesc *> paramList)
- : SimObject(name)
-{
- numFU = 0;
-
- funcUnits.clear();
-
- for (int i = 0; i < Num_OpClasses; ++i) {
- maxOpLatencies[i] = 0;
- maxIssueLatencies[i] = 0;
- }
-
- //
- // Iterate through the list of FUDescData structures
- //
- for (FUDDiterator i = paramList.begin(); i != paramList.end(); ++i) {
-
- //
- // Don't bother with this if we're not going to create any FU's
- //
- if ((*i)->number) {
- //
- // Create the FuncUnit object from this structure
- // - add the capabilities listed in the FU's operation
- // description
- //
- // We create the first unit, then duplicate it as needed
- //
- FuncUnit *fu = new FuncUnit;
-
- OPDDiterator j = (*i)->opDescList.begin();
- OPDDiterator end = (*i)->opDescList.end();
- for (; j != end; ++j) {
- // indicate that this pool has this capability
- capabilityList.set((*j)->opClass);
-
- // Add each of the FU's that will have this capability to the
- // appropriate queue.
- for (int k = 0; k < (*i)->number; ++k)
- fuPerCapList[(*j)->opClass].addFU(numFU + k);
-
- // indicate that this FU has the capability
- fu->addCapability((*j)->opClass, (*j)->opLat, (*j)->issueLat);
-
- if ((*j)->opLat > maxOpLatencies[(*j)->opClass])
- maxOpLatencies[(*j)->opClass] = (*j)->opLat;
-
- if ((*j)->issueLat > maxIssueLatencies[(*j)->opClass])
- maxIssueLatencies[(*j)->opClass] = (*j)->issueLat;
- }
-
- numFU++;
-
- // Add the appropriate number of copies of this FU to the list
- ostringstream s;
-
- s << (*i)->name() << "(0)";
- fu->name = s.str();
- funcUnits.push_back(fu);
-
- for (int c = 1; c < (*i)->number; ++c) {
- ostringstream s;
- numFU++;
- FuncUnit *fu2 = new FuncUnit(*fu);
-
- s << (*i)->name() << "(" << c << ")";
- fu2->name = s.str();
- funcUnits.push_back(fu2);
- }
- }
- }
-
- unitBusy.resize(numFU);
-
- for (int i = 0; i < numFU; i++) {
- unitBusy[i] = false;
- }
-}
-
-void
-FUPool::annotateMemoryUnits(unsigned hit_latency)
-{
- maxOpLatencies[MemReadOp] = hit_latency;
-
- fuListIterator i = funcUnits.begin();
- fuListIterator iend = funcUnits.end();
- for (; i != iend; ++i) {
- if ((*i)->provides(MemReadOp))
- (*i)->opLatency(MemReadOp) = hit_latency;
-
- if ((*i)->provides(MemWriteOp))
- (*i)->opLatency(MemWriteOp) = hit_latency;
- }
-}
-
-int
-FUPool::getUnit(OpClass capability)
-{
- // If this pool doesn't have the specified capability,
- // return this information to the caller
- if (!capabilityList[capability])
- return -2;
-
- int fu_idx = fuPerCapList[capability].getFU();
- int start_idx = fu_idx;
-
- // Iterate through the circular queue if needed, stopping if we've reached
- // the first element again.
- while (unitBusy[fu_idx]) {
- fu_idx = fuPerCapList[capability].getFU();
- if (fu_idx == start_idx) {
- // No FU available
- return -1;
- }
- }
-
- assert(fu_idx < numFU);
-
- unitBusy[fu_idx] = true;
-
- return fu_idx;
-}
-
-void
-FUPool::freeUnitNextCycle(int fu_idx)
-{
- assert(unitBusy[fu_idx]);
- unitsToBeFreed.push_back(fu_idx);
-}
-
-void
-FUPool::processFreeUnits()
-{
- while (!unitsToBeFreed.empty()) {
- int fu_idx = unitsToBeFreed.back();
- unitsToBeFreed.pop_back();
-
- assert(unitBusy[fu_idx]);
-
- unitBusy[fu_idx] = false;
- }
-}
-
-void
-FUPool::dump()
-{
- cout << "Function Unit Pool (" << name() << ")\n";
- cout << "======================================\n";
- cout << "Free List:\n";
-
- for (int i = 0; i < numFU; ++i) {
- if (unitBusy[i]) {
- continue;
- }
-
- cout << " [" << i << "] : ";
-
- cout << funcUnits[i]->name << " ";
-
- cout << "\n";
- }
-
- cout << "======================================\n";
- cout << "Busy List:\n";
- for (int i = 0; i < numFU; ++i) {
- if (!unitBusy[i]) {
- continue;
- }
-
- cout << " [" << i << "] : ";
-
- cout << funcUnits[i]->name << " ";
-
- cout << "\n";
- }
-}
-
-void
-FUPool::switchOut()
-{
-}
-
-void
-FUPool::takeOverFrom()
-{
- for (int i = 0; i < numFU; i++) {
- unitBusy[i] = false;
- }
- unitsToBeFreed.clear();
-}
-
-//
-
-////////////////////////////////////////////////////////////////////////////
-//
-// The SimObjects we use to get the FU information into the simulator
-//
-////////////////////////////////////////////////////////////////////////////
-
-//
-// FUPool - Contails a list of FUDesc objects to make available
-//
-
-//
-// The FuPool object
-//
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(FUPool)
-
- SimObjectVectorParam<FUDesc *> FUList;
-
-END_DECLARE_SIM_OBJECT_PARAMS(FUPool)
-
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(FUPool)
-
- INIT_PARAM(FUList, "list of FU's for this pool")
-
-END_INIT_SIM_OBJECT_PARAMS(FUPool)
-
-
-CREATE_SIM_OBJECT(FUPool)
-{
- return new FUPool(getInstanceName(), FUList);
-}
-
-REGISTER_SIM_OBJECT("FUPool", FUPool)
-
diff --git a/cpu/o3/fu_pool.hh b/cpu/o3/fu_pool.hh
deleted file mode 100644
index 052e4832d..000000000
--- a/cpu/o3/fu_pool.hh
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_FU_POOL_HH__
-#define __CPU_O3_FU_POOL_HH__
-
-#include <bitset>
-#include <list>
-#include <string>
-#include <vector>
-
-#include "base/sched_list.hh"
-#include "encumbered/cpu/full/op_class.hh"
-#include "sim/sim_object.hh"
-
-class FUDesc;
-class FuncUnit;
-
-/**
- * Pool of FU's, specific to the new CPU model. The old FU pool had lists of
- * free units and busy units, and whenever a FU was needed it would iterate
- * through the free units to find a FU that provided the capability. This pool
- * has lists of units specific to each of the capabilities, and whenever a FU
- * is needed, it iterates through that list to find a free unit. The previous
- * FU pool would have to be ticked each cycle to update which units became
- * free. This FU pool lets the IEW stage handle freeing units, which frees
- * them as their scheduled execution events complete. This limits units in this
- * model to either have identical issue and op latencies, or 1 cycle issue
- * latencies.
- */
-class FUPool : public SimObject
-{
- private:
- /** Maximum op execution latencies, per op class. */
- unsigned maxOpLatencies[Num_OpClasses];
- /** Maximum issue latencies, per op class. */
- unsigned maxIssueLatencies[Num_OpClasses];
-
- /** Bitvector listing capabilities of this FU pool. */
- std::bitset<Num_OpClasses> capabilityList;
-
- /** Bitvector listing which FUs are busy. */
- std::vector<bool> unitBusy;
-
- /** List of units to be freed at the end of this cycle. */
- std::vector<int> unitsToBeFreed;
-
- /**
- * Class that implements a circular queue to hold FU indices. The hope is
- * that FUs that have been just used will be moved to the end of the queue
- * by iterating through it, thus leaving free units at the head of the
- * queue.
- */
- class FUIdxQueue {
- public:
- /** Constructs a circular queue of FU indices. */
- FUIdxQueue()
- : idx(0), size(0)
- { }
-
- /** Adds a FU to the queue. */
- inline void addFU(int fu_idx);
-
- /** Returns the index of the FU at the head of the queue, and changes
- * the index to the next element.
- */
- inline int getFU();
-
- private:
- /** Circular queue index. */
- int idx;
-
- /** Size of the queue. */
- int size;
-
- /** Queue of FU indices. */
- std::vector<int> funcUnitsIdx;
- };
-
- /** Per op class queues of FUs that provide that capability. */
- FUIdxQueue fuPerCapList[Num_OpClasses];
-
- /** Number of FUs. */
- int numFU;
-
- /** Functional units. */
- std::vector<FuncUnit *> funcUnits;
-
- typedef std::vector<FuncUnit *>::iterator fuListIterator;
-
- public:
-
- /** Constructs a FU pool. */
- FUPool(std::string name, std::vector<FUDesc *> l);
- ~FUPool();
-
- /** Annotates units that provide memory operations. Included only because
- * old FU pool provided this function.
- */
- void annotateMemoryUnits(unsigned hit_latency);
-
- /**
- * Gets a FU providing the requested capability. Will mark the unit as busy,
- * but leaves the freeing of the unit up to the IEW stage.
- * @param capability The capability requested.
- * @return Returns -2 if the FU pool does not have the capability, -1 if
- * there is no free FU, and the FU's index otherwise.
- */
- int getUnit(OpClass capability);
-
- /** Frees a FU at the end of this cycle. */
- void freeUnitNextCycle(int fu_idx);
-
- /** Frees all FUs on the list. */
- void processFreeUnits();
-
- /** Returns the total number of FUs. */
- int size() { return numFU; }
-
- /** Debugging function used to dump FU information. */
- void dump();
-
- /** Returns the operation execution latency of the given capability. */
- unsigned getOpLatency(OpClass capability) {
- return maxOpLatencies[capability];
- }
-
- /** Returns the issue latency of the given capability. */
- unsigned getIssueLatency(OpClass capability) {
- return maxIssueLatencies[capability];
- }
-
- /** Switches out functional unit pool. */
- void switchOut();
-
- /** Takes over from another CPU's thread. */
- void takeOverFrom();
-};
-
-#endif // __CPU_O3_FU_POOL_HH__
diff --git a/cpu/o3/iew.cc b/cpu/o3/iew.cc
deleted file mode 100644
index 90d035f71..000000000
--- a/cpu/o3/iew.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/o3/alpha_dyn_inst.hh"
-#include "cpu/o3/alpha_impl.hh"
-#include "cpu/o3/iew_impl.hh"
-#include "cpu/o3/inst_queue.hh"
-
-template class DefaultIEW<AlphaSimpleImpl>;
diff --git a/cpu/o3/iew.hh b/cpu/o3/iew.hh
deleted file mode 100644
index eda6a6bc0..000000000
--- a/cpu/o3/iew.hh
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_IEW_HH__
-#define __CPU_O3_IEW_HH__
-
-#include <queue>
-
-#include "base/statistics.hh"
-#include "base/timebuf.hh"
-#include "config/full_system.hh"
-#include "cpu/o3/comm.hh"
-#include "cpu/o3/scoreboard.hh"
-#include "cpu/o3/lsq.hh"
-
-class FUPool;
-
-/**
- * DefaultIEW handles both single threaded and SMT IEW
- * (issue/execute/writeback). It handles the dispatching of
- * instructions to the LSQ/IQ as part of the issue stage, and has the
- * IQ try to issue instructions each cycle. The execute latency is
- * actually tied into the issue latency to allow the IQ to be able to
- * do back-to-back scheduling without having to speculatively schedule
- * instructions. This happens by having the IQ have access to the
- * functional units, and the IQ gets the execution latencies from the
- * FUs when it issues instructions. Instructions reach the execute
- * stage on the last cycle of their execution, which is when the IQ
- * knows to wake up any dependent instructions, allowing back to back
- * scheduling. The execute portion of IEW separates memory
- * instructions from non-memory instructions, either telling the LSQ
- * to execute the instruction, or executing the instruction directly.
- * The writeback portion of IEW completes the instructions by waking
- * up any dependents, and marking the register ready on the
- * scoreboard.
- */
-template<class Impl>
-class DefaultIEW
-{
- private:
- //Typedefs from Impl
- typedef typename Impl::CPUPol CPUPol;
- typedef typename Impl::DynInstPtr DynInstPtr;
- typedef typename Impl::FullCPU FullCPU;
- typedef typename Impl::Params Params;
-
- typedef typename CPUPol::IQ IQ;
- typedef typename CPUPol::RenameMap RenameMap;
- typedef typename CPUPol::LSQ LSQ;
-
- typedef typename CPUPol::TimeStruct TimeStruct;
- typedef typename CPUPol::IEWStruct IEWStruct;
- typedef typename CPUPol::RenameStruct RenameStruct;
- typedef typename CPUPol::IssueStruct IssueStruct;
-
- friend class Impl::FullCPU;
- friend class CPUPol::IQ;
-
- public:
- /** Overall IEW stage status. Used to determine if the CPU can
- * deschedule itself due to a lack of activity.
- */
- enum Status {
- Active,
- Inactive
- };
-
- /** Status for Issue, Execute, and Writeback stages. */
- enum StageStatus {
- Running,
- Blocked,
- Idle,
- StartSquash,
- Squashing,
- Unblocking
- };
-
- private:
- /** Overall stage status. */
- Status _status;
- /** Dispatch status. */
- StageStatus dispatchStatus[Impl::MaxThreads];
- /** Execute status. */
- StageStatus exeStatus;
- /** Writeback status. */
- StageStatus wbStatus;
-
- public:
- /** LdWriteback event for a load completion. */
- class LdWritebackEvent : public Event {
- private:
- /** Instruction that is writing back data to the register file. */
- DynInstPtr inst;
- /** Pointer to IEW stage. */
- DefaultIEW<Impl> *iewStage;
-
- public:
- /** Constructs a load writeback event. */
- LdWritebackEvent(DynInstPtr &_inst, DefaultIEW<Impl> *_iew);
-
- /** Processes writeback event. */
- virtual void process();
- /** Returns the description of the writeback event. */
- virtual const char *description();
- };
-
- public:
- /** Constructs a DefaultIEW with the given parameters. */
- DefaultIEW(Params *params);
-
- /** Returns the name of the DefaultIEW stage. */
- std::string name() const;
-
- /** Registers statistics. */
- void regStats();
-
- /** Initializes stage; sends back the number of free IQ and LSQ entries. */
- void initStage();
-
- /** Sets CPU pointer for IEW, IQ, and LSQ. */
- void setCPU(FullCPU *cpu_ptr);
-
- /** Sets main time buffer used for backwards communication. */
- void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
-
- /** Sets time buffer for getting instructions coming from rename. */
- void setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr);
-
- /** Sets time buffer to pass on instructions to commit. */
- void setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr);
-
- /** Sets pointer to list of active threads. */
- void setActiveThreads(std::list<unsigned> *at_ptr);
-
- /** Sets pointer to the scoreboard. */
- void setScoreboard(Scoreboard *sb_ptr);
-
- /** Starts switch out of IEW stage. */
- void switchOut();
-
- /** Completes switch out of IEW stage. */
- void doSwitchOut();
-
- /** Takes over from another CPU's thread. */
- void takeOverFrom();
-
- /** Returns if IEW is switched out. */
- bool isSwitchedOut() { return switchedOut; }
-
- /** Sets page table pointer within LSQ. */
-// void setPageTable(PageTable *pt_ptr);
-
- /** Squashes instructions in IEW for a specific thread. */
- void squash(unsigned tid);
-
- /** Wakes all dependents of a completed instruction. */
- void wakeDependents(DynInstPtr &inst);
-
- /** Tells memory dependence unit that a memory instruction needs to be
- * rescheduled. It will re-execute once replayMemInst() is called.
- */
- void rescheduleMemInst(DynInstPtr &inst);
-
- /** Re-executes all rescheduled memory instructions. */
- void replayMemInst(DynInstPtr &inst);
-
- /** Sends an instruction to commit through the time buffer. */
- void instToCommit(DynInstPtr &inst);
-
- /** Inserts unused instructions of a thread into the skid buffer. */
- void skidInsert(unsigned tid);
-
- /** Returns the max of the number of entries in all of the skid buffers. */
- int skidCount();
-
- /** Returns if all of the skid buffers are empty. */
- bool skidsEmpty();
-
- /** Updates overall IEW status based on all of the stages' statuses. */
- void updateStatus();
-
- /** Resets entries of the IQ and the LSQ. */
- void resetEntries();
-
- /** Tells the CPU to wakeup if it has descheduled itself due to no
- * activity. Used mainly by the LdWritebackEvent.
- */
- void wakeCPU();
-
- /** Reports to the CPU that there is activity this cycle. */
- void activityThisCycle();
-
- /** Tells CPU that the IEW stage is active and running. */
- inline void activateStage();
-
- /** Tells CPU that the IEW stage is inactive and idle. */
- inline void deactivateStage();
-
- /** Returns if the LSQ has any stores to writeback. */
- bool hasStoresToWB() { return ldstQueue.hasStoresToWB(); }
-
- private:
- /** Sends commit proper information for a squash due to a branch
- * mispredict.
- */
- void squashDueToBranch(DynInstPtr &inst, unsigned thread_id);
-
- /** Sends commit proper information for a squash due to a memory order
- * violation.
- */
- void squashDueToMemOrder(DynInstPtr &inst, unsigned thread_id);
-
- /** Sends commit proper information for a squash due to memory becoming
- * blocked (younger issued instructions must be retried).
- */
- void squashDueToMemBlocked(DynInstPtr &inst, unsigned thread_id);
-
- /** Sets Dispatch to blocked, and signals back to other stages to block. */
- void block(unsigned thread_id);
-
- /** Unblocks Dispatch if the skid buffer is empty, and signals back to
- * other stages to unblock.
- */
- void unblock(unsigned thread_id);
-
- /** Determines proper actions to take given Dispatch's status. */
- void dispatch(unsigned tid);
-
- /** Dispatches instructions to IQ and LSQ. */
- void dispatchInsts(unsigned tid);
-
- /** Executes instructions. In the case of memory operations, it informs the
- * LSQ to execute the instructions. Also handles any redirects that occur
- * due to the executed instructions.
- */
- void executeInsts();
-
- /** Writebacks instructions. In our model, the instruction's execute()
- * function atomically reads registers, executes, and writes registers.
- * Thus this writeback only wakes up dependent instructions, and informs
- * the scoreboard of registers becoming ready.
- */
- void writebackInsts();
-
- /** Returns the number of valid, non-squashed instructions coming from
- * rename to dispatch.
- */
- unsigned validInstsFromRename();
-
- /** Reads the stall signals. */
- void readStallSignals(unsigned tid);
-
- /** Checks if any of the stall conditions are currently true. */
- bool checkStall(unsigned tid);
-
- /** Processes inputs and changes state accordingly. */
- void checkSignalsAndUpdate(unsigned tid);
-
- /** Sorts instructions coming from rename into lists separated by thread. */
- void sortInsts();
-
- public:
- /** Ticks IEW stage, causing Dispatch, the IQ, the LSQ, Execute, and
- * Writeback to run for one cycle.
- */
- void tick();
-
- private:
- /** Updates execution stats based on the instruction. */
- void updateExeInstStats(DynInstPtr &inst);
-
- /** Pointer to main time buffer used for backwards communication. */
- TimeBuffer<TimeStruct> *timeBuffer;
-
- /** Wire to write information heading to previous stages. */
- typename TimeBuffer<TimeStruct>::wire toFetch;
-
- /** Wire to get commit's output from backwards time buffer. */
- typename TimeBuffer<TimeStruct>::wire fromCommit;
-
- /** Wire to write information heading to previous stages. */
- typename TimeBuffer<TimeStruct>::wire toRename;
-
- /** Rename instruction queue interface. */
- TimeBuffer<RenameStruct> *renameQueue;
-
- /** Wire to get rename's output from rename queue. */
- typename TimeBuffer<RenameStruct>::wire fromRename;
-
- /** Issue stage queue. */
- TimeBuffer<IssueStruct> issueToExecQueue;
-
- /** Wire to read information from the issue stage time queue. */
- typename TimeBuffer<IssueStruct>::wire fromIssue;
-
- /**
- * IEW stage time buffer. Holds ROB indices of instructions that
- * can be marked as completed.
- */
- TimeBuffer<IEWStruct> *iewQueue;
-
- /** Wire to write infromation heading to commit. */
- typename TimeBuffer<IEWStruct>::wire toCommit;
-
- /** Queue of all instructions coming from rename this cycle. */
- std::queue<DynInstPtr> insts[Impl::MaxThreads];
-
- /** Skid buffer between rename and IEW. */
- std::queue<DynInstPtr> skidBuffer[Impl::MaxThreads];
-
- /** Scoreboard pointer. */
- Scoreboard* scoreboard;
-
- public:
- /** Instruction queue. */
- IQ instQueue;
-
- /** Load / store queue. */
- LSQ ldstQueue;
-
- /** Pointer to the functional unit pool. */
- FUPool *fuPool;
-
- private:
- /** CPU pointer. */
- FullCPU *cpu;
-
- /** Records if IEW has written to the time buffer this cycle, so that the
- * CPU can deschedule itself if there is no activity.
- */
- bool wroteToTimeBuffer;
-
- /** Source of possible stalls. */
- struct Stalls {
- bool commit;
- };
-
- /** Stages that are telling IEW to stall. */
- Stalls stalls[Impl::MaxThreads];
-
- /** Debug function to print instructions that are issued this cycle. */
- void printAvailableInsts();
-
- public:
- /** Records if the LSQ needs to be updated on the next cycle, so that
- * IEW knows if there will be activity on the next cycle.
- */
- bool updateLSQNextCycle;
-
- private:
- /** Records if there is a fetch redirect on this cycle for each thread. */
- bool fetchRedirect[Impl::MaxThreads];
-
- /** Used to track if all instructions have been dispatched this cycle.
- * If they have not, then blocking must have occurred, and the instructions
- * would already be added to the skid buffer.
- * @todo: Fix this hack.
- */
- bool dispatchedAllInsts;
-
- /** Records if the queues have been changed (inserted or issued insts),
- * so that IEW knows to broadcast the updated amount of free entries.
- */
- bool updatedQueues;
-
- /** Commit to IEW delay, in ticks. */
- unsigned commitToIEWDelay;
-
- /** Rename to IEW delay, in ticks. */
- unsigned renameToIEWDelay;
-
- /**
- * Issue to execute delay, in ticks. What this actually represents is
- * the amount of time it takes for an instruction to wake up, be
- * scheduled, and sent to a FU for execution.
- */
- unsigned issueToExecuteDelay;
-
- /** Width of issue's read path, in instructions. The read path is both
- * the skid buffer and the rename instruction queue.
- * Note to self: is this really different than issueWidth?
- */
- unsigned issueReadWidth;
-
- /** Width of issue, in instructions. */
- unsigned issueWidth;
-
- /** Width of execute, in instructions. Might make more sense to break
- * down into FP vs int.
- */
- unsigned executeWidth;
-
- /** Index into queue of instructions being written back. */
- unsigned wbNumInst;
-
- /** Cycle number within the queue of instructions being written back.
- * Used in case there are too many instructions writing back at the current
- * cycle and writesbacks need to be scheduled for the future. See comments
- * in instToCommit().
- */
- unsigned wbCycle;
-
- /** Number of active threads. */
- unsigned numThreads;
-
- /** Pointer to list of active threads. */
- std::list<unsigned> *activeThreads;
-
- /** Maximum size of the skid buffer. */
- unsigned skidBufferMax;
-
- /** Is this stage switched out. */
- bool switchedOut;
-
- /** Stat for total number of idle cycles. */
- Stats::Scalar<> iewIdleCycles;
- /** Stat for total number of squashing cycles. */
- Stats::Scalar<> iewSquashCycles;
- /** Stat for total number of blocking cycles. */
- Stats::Scalar<> iewBlockCycles;
- /** Stat for total number of unblocking cycles. */
- Stats::Scalar<> iewUnblockCycles;
- /** Stat for total number of instructions dispatched. */
- Stats::Scalar<> iewDispatchedInsts;
- /** Stat for total number of squashed instructions dispatch skips. */
- Stats::Scalar<> iewDispSquashedInsts;
- /** Stat for total number of dispatched load instructions. */
- Stats::Scalar<> iewDispLoadInsts;
- /** Stat for total number of dispatched store instructions. */
- Stats::Scalar<> iewDispStoreInsts;
- /** Stat for total number of dispatched non speculative instructions. */
- Stats::Scalar<> iewDispNonSpecInsts;
- /** Stat for number of times the IQ becomes full. */
- Stats::Scalar<> iewIQFullEvents;
- /** Stat for number of times the LSQ becomes full. */
- Stats::Scalar<> iewLSQFullEvents;
- /** Stat for total number of executed instructions. */
- Stats::Scalar<> iewExecutedInsts;
- /** Stat for total number of executed load instructions. */
- Stats::Vector<> iewExecLoadInsts;
- /** Stat for total number of executed store instructions. */
-// Stats::Scalar<> iewExecStoreInsts;
- /** Stat for total number of squashed instructions skipped at execute. */
- Stats::Scalar<> iewExecSquashedInsts;
- /** Stat for total number of memory ordering violation events. */
- Stats::Scalar<> memOrderViolationEvents;
- /** Stat for total number of incorrect predicted taken branches. */
- Stats::Scalar<> predictedTakenIncorrect;
- /** Stat for total number of incorrect predicted not taken branches. */
- Stats::Scalar<> predictedNotTakenIncorrect;
- /** Stat for total number of mispredicted branches detected at execute. */
- Stats::Formula branchMispredicts;
-
- /** Number of executed software prefetches. */
- Stats::Vector<> exeSwp;
- /** Number of executed nops. */
- Stats::Vector<> exeNop;
- /** Number of executed meomory references. */
- Stats::Vector<> exeRefs;
- /** Number of executed branches. */
- Stats::Vector<> exeBranches;
-
-// Stats::Vector<> issued_ops;
-/*
- Stats::Vector<> stat_fu_busy;
- Stats::Vector2d<> stat_fuBusy;
- Stats::Vector<> dist_unissued;
- Stats::Vector2d<> stat_issued_inst_type;
-*/
- /** Number of instructions issued per cycle. */
- Stats::Formula issueRate;
- /** Number of executed store instructions. */
- Stats::Formula iewExecStoreInsts;
-// Stats::Formula issue_op_rate;
-// Stats::Formula fu_busy_rate;
- /** Number of instructions sent to commit. */
- Stats::Vector<> iewInstsToCommit;
- /** Number of instructions that writeback. */
- Stats::Vector<> writebackCount;
- /** Number of instructions that wake consumers. */
- Stats::Vector<> producerInst;
- /** Number of instructions that wake up from producers. */
- Stats::Vector<> consumerInst;
- /** Number of instructions that were delayed in writing back due
- * to resource contention.
- */
- Stats::Vector<> wbPenalized;
-
- /** Number of instructions per cycle written back. */
- Stats::Formula wbRate;
- /** Average number of woken instructions per writeback. */
- Stats::Formula wbFanout;
- /** Number of instructions per cycle delayed in writing back . */
- Stats::Formula wbPenalizedRate;
-};
-
-#endif // __CPU_O3_IEW_HH__
diff --git a/cpu/o3/iew_impl.hh b/cpu/o3/iew_impl.hh
deleted file mode 100644
index 3ed20cb75..000000000
--- a/cpu/o3/iew_impl.hh
+++ /dev/null
@@ -1,1587 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-// @todo: Fix the instantaneous communication among all the stages within
-// iew. There's a clear delay between issue and execute, yet backwards
-// communication happens simultaneously.
-
-#include <queue>
-
-#include "base/timebuf.hh"
-#include "cpu/o3/fu_pool.hh"
-#include "cpu/o3/iew.hh"
-
-using namespace std;
-
-template<class Impl>
-DefaultIEW<Impl>::LdWritebackEvent::LdWritebackEvent(DynInstPtr &_inst,
- DefaultIEW<Impl> *_iew)
- : Event(&mainEventQueue), inst(_inst), iewStage(_iew)
-{
- this->setFlags(Event::AutoDelete);
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::LdWritebackEvent::process()
-{
- DPRINTF(IEW, "Load writeback event [sn:%lli]\n", inst->seqNum);
- DPRINTF(Activity, "Activity: Ld Writeback event [sn:%lli]\n", inst->seqNum);
-
- //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum);
-
- if (iewStage->isSwitchedOut()) {
- inst = NULL;
- return;
- } else if (inst->isSquashed()) {
- iewStage->wakeCPU();
- inst = NULL;
- return;
- }
-
- iewStage->wakeCPU();
-
- if (!inst->isExecuted()) {
- inst->setExecuted();
-
- // Complete access to copy data to proper place.
- if (inst->isStore()) {
- inst->completeAcc();
- }
- }
-
- // Need to insert instruction into queue to commit
- iewStage->instToCommit(inst);
-
- iewStage->activityThisCycle();
-
- inst = NULL;
-}
-
-template<class Impl>
-const char *
-DefaultIEW<Impl>::LdWritebackEvent::description()
-{
- return "Load writeback event";
-}
-
-template<class Impl>
-DefaultIEW<Impl>::DefaultIEW(Params *params)
- : // @todo: Make this into a parameter.
- issueToExecQueue(5, 5),
- instQueue(params),
- ldstQueue(params),
- fuPool(params->fuPool),
- commitToIEWDelay(params->commitToIEWDelay),
- renameToIEWDelay(params->renameToIEWDelay),
- issueToExecuteDelay(params->issueToExecuteDelay),
- issueReadWidth(params->issueWidth),
- issueWidth(params->issueWidth),
- executeWidth(params->executeWidth),
- numThreads(params->numberOfThreads),
- switchedOut(false)
-{
- _status = Active;
- exeStatus = Running;
- wbStatus = Idle;
-
- // Setup wire to read instructions coming from issue.
- fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay);
-
- // Instruction queue needs the queue between issue and execute.
- instQueue.setIssueToExecuteQueue(&issueToExecQueue);
-
- instQueue.setIEW(this);
- ldstQueue.setIEW(this);
-
- for (int i=0; i < numThreads; i++) {
- dispatchStatus[i] = Running;
- stalls[i].commit = false;
- fetchRedirect[i] = false;
- }
-
- updateLSQNextCycle = false;
-
- skidBufferMax = (3 * (renameToIEWDelay * params->renameWidth)) + issueWidth;
-}
-
-template <class Impl>
-std::string
-DefaultIEW<Impl>::name() const
-{
- return cpu->name() + ".iew";
-}
-
-template <class Impl>
-void
-DefaultIEW<Impl>::regStats()
-{
- using namespace Stats;
-
- instQueue.regStats();
-
- iewIdleCycles
- .name(name() + ".iewIdleCycles")
- .desc("Number of cycles IEW is idle");
-
- iewSquashCycles
- .name(name() + ".iewSquashCycles")
- .desc("Number of cycles IEW is squashing");
-
- iewBlockCycles
- .name(name() + ".iewBlockCycles")
- .desc("Number of cycles IEW is blocking");
-
- iewUnblockCycles
- .name(name() + ".iewUnblockCycles")
- .desc("Number of cycles IEW is unblocking");
-
- iewDispatchedInsts
- .name(name() + ".iewDispatchedInsts")
- .desc("Number of instructions dispatched to IQ");
-
- iewDispSquashedInsts
- .name(name() + ".iewDispSquashedInsts")
- .desc("Number of squashed instructions skipped by dispatch");
-
- iewDispLoadInsts
- .name(name() + ".iewDispLoadInsts")
- .desc("Number of dispatched load instructions");
-
- iewDispStoreInsts
- .name(name() + ".iewDispStoreInsts")
- .desc("Number of dispatched store instructions");
-
- iewDispNonSpecInsts
- .name(name() + ".iewDispNonSpecInsts")
- .desc("Number of dispatched non-speculative instructions");
-
- iewIQFullEvents
- .name(name() + ".iewIQFullEvents")
- .desc("Number of times the IQ has become full, causing a stall");
-
- iewLSQFullEvents
- .name(name() + ".iewLSQFullEvents")
- .desc("Number of times the LSQ has become full, causing a stall");
-
- iewExecutedInsts
- .name(name() + ".iewExecutedInsts")
- .desc("Number of executed instructions");
-
- iewExecLoadInsts
- .init(cpu->number_of_threads)
- .name(name() + ".iewExecLoadInsts")
- .desc("Number of load instructions executed")
- .flags(total);
-
- iewExecSquashedInsts
- .name(name() + ".iewExecSquashedInsts")
- .desc("Number of squashed instructions skipped in execute");
-
- memOrderViolationEvents
- .name(name() + ".memOrderViolationEvents")
- .desc("Number of memory order violations");
-
- predictedTakenIncorrect
- .name(name() + ".predictedTakenIncorrect")
- .desc("Number of branches that were predicted taken incorrectly");
-
- predictedNotTakenIncorrect
- .name(name() + ".predictedNotTakenIncorrect")
- .desc("Number of branches that were predicted not taken incorrectly");
-
- branchMispredicts
- .name(name() + ".branchMispredicts")
- .desc("Number of branch mispredicts detected at execute");
-
- branchMispredicts = predictedTakenIncorrect + predictedNotTakenIncorrect;
-
- exeSwp
- .init(cpu->number_of_threads)
- .name(name() + ".EXEC:swp")
- .desc("number of swp insts executed")
- .flags(total)
- ;
-
- exeNop
- .init(cpu->number_of_threads)
- .name(name() + ".EXEC:nop")
- .desc("number of nop insts executed")
- .flags(total)
- ;
-
- exeRefs
- .init(cpu->number_of_threads)
- .name(name() + ".EXEC:refs")
- .desc("number of memory reference insts executed")
- .flags(total)
- ;
-
- exeBranches
- .init(cpu->number_of_threads)
- .name(name() + ".EXEC:branches")
- .desc("Number of branches executed")
- .flags(total)
- ;
-
- issueRate
- .name(name() + ".EXEC:rate")
- .desc("Inst execution rate")
- .flags(total)
- ;
- issueRate = iewExecutedInsts / cpu->numCycles;
-
- iewExecStoreInsts
- .name(name() + ".EXEC:stores")
- .desc("Number of stores executed")
- .flags(total)
- ;
- iewExecStoreInsts = exeRefs - iewExecLoadInsts;
-/*
- for (int i=0; i<Num_OpClasses; ++i) {
- stringstream subname;
- subname << opClassStrings[i] << "_delay";
- issue_delay_dist.subname(i, subname.str());
- }
-*/
- //
- // Other stats
- //
-
- iewInstsToCommit
- .init(cpu->number_of_threads)
- .name(name() + ".WB:sent")
- .desc("cumulative count of insts sent to commit")
- .flags(total)
- ;
-
- writebackCount
- .init(cpu->number_of_threads)
- .name(name() + ".WB:count")
- .desc("cumulative count of insts written-back")
- .flags(total)
- ;
-
- producerInst
- .init(cpu->number_of_threads)
- .name(name() + ".WB:producers")
- .desc("num instructions producing a value")
- .flags(total)
- ;
-
- consumerInst
- .init(cpu->number_of_threads)
- .name(name() + ".WB:consumers")
- .desc("num instructions consuming a value")
- .flags(total)
- ;
-
- wbPenalized
- .init(cpu->number_of_threads)
- .name(name() + ".WB:penalized")
- .desc("number of instrctions required to write to 'other' IQ")
- .flags(total)
- ;
-
- wbPenalizedRate
- .name(name() + ".WB:penalized_rate")
- .desc ("fraction of instructions written-back that wrote to 'other' IQ")
- .flags(total)
- ;
-
- wbPenalizedRate = wbPenalized / writebackCount;
-
- wbFanout
- .name(name() + ".WB:fanout")
- .desc("average fanout of values written-back")
- .flags(total)
- ;
-
- wbFanout = producerInst / consumerInst;
-
- wbRate
- .name(name() + ".WB:rate")
- .desc("insts written-back per cycle")
- .flags(total)
- ;
- wbRate = writebackCount / cpu->numCycles;
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::initStage()
-{
- for (int tid=0; tid < numThreads; tid++) {
- toRename->iewInfo[tid].usedIQ = true;
- toRename->iewInfo[tid].freeIQEntries =
- instQueue.numFreeEntries(tid);
-
- toRename->iewInfo[tid].usedLSQ = true;
- toRename->iewInfo[tid].freeLSQEntries =
- ldstQueue.numFreeEntries(tid);
- }
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::setCPU(FullCPU *cpu_ptr)
-{
- DPRINTF(IEW, "Setting CPU pointer.\n");
- cpu = cpu_ptr;
-
- instQueue.setCPU(cpu_ptr);
- ldstQueue.setCPU(cpu_ptr);
-
- cpu->activateStage(FullCPU::IEWIdx);
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
-{
- DPRINTF(IEW, "Setting time buffer pointer.\n");
- timeBuffer = tb_ptr;
-
- // Setup wire to read information from time buffer, from commit.
- fromCommit = timeBuffer->getWire(-commitToIEWDelay);
-
- // Setup wire to write information back to previous stages.
- toRename = timeBuffer->getWire(0);
-
- toFetch = timeBuffer->getWire(0);
-
- // Instruction queue also needs main time buffer.
- instQueue.setTimeBuffer(tb_ptr);
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
-{
- DPRINTF(IEW, "Setting rename queue pointer.\n");
- renameQueue = rq_ptr;
-
- // Setup wire to read information from rename queue.
- fromRename = renameQueue->getWire(-renameToIEWDelay);
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
-{
- DPRINTF(IEW, "Setting IEW queue pointer.\n");
- iewQueue = iq_ptr;
-
- // Setup wire to write instructions to commit.
- toCommit = iewQueue->getWire(0);
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::setActiveThreads(list<unsigned> *at_ptr)
-{
- DPRINTF(IEW, "Setting active threads list pointer.\n");
- activeThreads = at_ptr;
-
- ldstQueue.setActiveThreads(at_ptr);
- instQueue.setActiveThreads(at_ptr);
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr)
-{
- DPRINTF(IEW, "Setting scoreboard pointer.\n");
- scoreboard = sb_ptr;
-}
-
-#if 0
-template<class Impl>
-void
-DefaultIEW<Impl>::setPageTable(PageTable *pt_ptr)
-{
- ldstQueue.setPageTable(pt_ptr);
-}
-#endif
-
-template <class Impl>
-void
-DefaultIEW<Impl>::switchOut()
-{
- // IEW is ready to switch out at any time.
- cpu->signalSwitched();
-}
-
-template <class Impl>
-void
-DefaultIEW<Impl>::doSwitchOut()
-{
- // Clear any state.
- switchedOut = true;
-
- instQueue.switchOut();
- ldstQueue.switchOut();
- fuPool->switchOut();
-
- for (int i = 0; i < numThreads; i++) {
- while (!insts[i].empty())
- insts[i].pop();
- while (!skidBuffer[i].empty())
- skidBuffer[i].pop();
- }
-}
-
-template <class Impl>
-void
-DefaultIEW<Impl>::takeOverFrom()
-{
- // Reset all state.
- _status = Active;
- exeStatus = Running;
- wbStatus = Idle;
- switchedOut = false;
-
- instQueue.takeOverFrom();
- ldstQueue.takeOverFrom();
- fuPool->takeOverFrom();
-
- initStage();
- cpu->activityThisCycle();
-
- for (int i=0; i < numThreads; i++) {
- dispatchStatus[i] = Running;
- stalls[i].commit = false;
- fetchRedirect[i] = false;
- }
-
- updateLSQNextCycle = false;
-
- // @todo: Fix hardcoded number
- for (int i = 0; i < 6; ++i) {
- issueToExecQueue.advance();
- }
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::squash(unsigned tid)
-{
- DPRINTF(IEW, "[tid:%i]: Squashing all instructions.\n",
- tid);
-
- // Tell the IQ to start squashing.
- instQueue.squash(tid);
-
- // Tell the LDSTQ to start squashing.
- ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum, tid);
-
- updatedQueues = true;
-
- // Clear the skid buffer in case it has any data in it.
- while (!skidBuffer[tid].empty()) {
-
- if (skidBuffer[tid].front()->isLoad() ||
- skidBuffer[tid].front()->isStore() ) {
- toRename->iewInfo[tid].dispatchedToLSQ++;
- }
-
- toRename->iewInfo[tid].dispatched++;
-
- skidBuffer[tid].pop();
- }
-
- while (!insts[tid].empty()) {
- if (insts[tid].front()->isLoad() ||
- insts[tid].front()->isStore() ) {
- toRename->iewInfo[tid].dispatchedToLSQ++;
- }
-
- toRename->iewInfo[tid].dispatched++;
-
- insts[tid].pop();
- }
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, unsigned tid)
-{
- DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %#x "
- "[sn:%i].\n", tid, inst->readPC(), inst->seqNum);
-
- toCommit->squash[tid] = true;
- toCommit->squashedSeqNum[tid] = inst->seqNum;
- toCommit->mispredPC[tid] = inst->readPC();
- toCommit->nextPC[tid] = inst->readNextPC();
- toCommit->branchMispredict[tid] = true;
- toCommit->branchTaken[tid] = inst->readNextPC() !=
- (inst->readPC() + sizeof(TheISA::MachInst));
-
- toCommit->includeSquashInst[tid] = false;
-
- wroteToTimeBuffer = true;
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, unsigned tid)
-{
- DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, "
- "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum);
-
- toCommit->squash[tid] = true;
- toCommit->squashedSeqNum[tid] = inst->seqNum;
- toCommit->nextPC[tid] = inst->readNextPC();
-
- toCommit->includeSquashInst[tid] = false;
-
- wroteToTimeBuffer = true;
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, unsigned tid)
-{
- DPRINTF(IEW, "[tid:%i]: Memory blocked, squashing load and younger insts, "
- "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum);
-
- toCommit->squash[tid] = true;
- toCommit->squashedSeqNum[tid] = inst->seqNum;
- toCommit->nextPC[tid] = inst->readPC();
-
- // Must include the broadcasted SN in the squash.
- toCommit->includeSquashInst[tid] = true;
-
- ldstQueue.setLoadBlockedHandled(tid);
-
- wroteToTimeBuffer = true;
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::block(unsigned tid)
-{
- DPRINTF(IEW, "[tid:%u]: Blocking.\n", tid);
-
- if (dispatchStatus[tid] != Blocked &&
- dispatchStatus[tid] != Unblocking) {
- toRename->iewBlock[tid] = true;
- wroteToTimeBuffer = true;
- }
-
- // Add the current inputs to the skid buffer so they can be
- // reprocessed when this stage unblocks.
- skidInsert(tid);
-
- dispatchStatus[tid] = Blocked;
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::unblock(unsigned tid)
-{
- DPRINTF(IEW, "[tid:%i]: Reading instructions out of the skid "
- "buffer %u.\n",tid, tid);
-
- // If the skid bufffer is empty, signal back to previous stages to unblock.
- // Also switch status to running.
- if (skidBuffer[tid].empty()) {
- toRename->iewUnblock[tid] = true;
- wroteToTimeBuffer = true;
- DPRINTF(IEW, "[tid:%i]: Done unblocking.\n",tid);
- dispatchStatus[tid] = Running;
- }
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::wakeDependents(DynInstPtr &inst)
-{
- instQueue.wakeDependents(inst);
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::rescheduleMemInst(DynInstPtr &inst)
-{
- instQueue.rescheduleMemInst(inst);
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::replayMemInst(DynInstPtr &inst)
-{
- instQueue.replayMemInst(inst);
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::instToCommit(DynInstPtr &inst)
-{
- // First check the time slot that this instruction will write
- // to. If there are free write ports at the time, then go ahead
- // and write the instruction to that time. If there are not,
- // keep looking back to see where's the first time there's a
- // free slot.
- while ((*iewQueue)[wbCycle].insts[wbNumInst]) {
- ++wbNumInst;
- if (wbNumInst == issueWidth) {
- ++wbCycle;
- wbNumInst = 0;
- }
-
- assert(wbCycle < 5);
- }
-
- // Add finished instruction to queue to commit.
- (*iewQueue)[wbCycle].insts[wbNumInst] = inst;
- (*iewQueue)[wbCycle].size++;
-}
-
-template <class Impl>
-unsigned
-DefaultIEW<Impl>::validInstsFromRename()
-{
- unsigned inst_count = 0;
-
- for (int i=0; i<fromRename->size; i++) {
- if (!fromRename->insts[i]->squashed)
- inst_count++;
- }
-
- return inst_count;
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::skidInsert(unsigned tid)
-{
- DynInstPtr inst = NULL;
-
- while (!insts[tid].empty()) {
- inst = insts[tid].front();
-
- insts[tid].pop();
-
- DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%#x into "
- "dispatch skidBuffer %i\n",tid, inst->seqNum,
- inst->readPC(),tid);
-
- skidBuffer[tid].push(inst);
- }
-
- assert(skidBuffer[tid].size() <= skidBufferMax &&
- "Skidbuffer Exceeded Max Size");
-}
-
-template<class Impl>
-int
-DefaultIEW<Impl>::skidCount()
-{
- int max=0;
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- unsigned thread_count = skidBuffer[*threads++].size();
- if (max < thread_count)
- max = thread_count;
- }
-
- return max;
-}
-
-template<class Impl>
-bool
-DefaultIEW<Impl>::skidsEmpty()
-{
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- if (!skidBuffer[*threads++].empty())
- return false;
- }
-
- return true;
-}
-
-template <class Impl>
-void
-DefaultIEW<Impl>::updateStatus()
-{
- bool any_unblocking = false;
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- if (dispatchStatus[tid] == Unblocking) {
- any_unblocking = true;
- break;
- }
- }
-
- // If there are no ready instructions waiting to be scheduled by the IQ,
- // and there's no stores waiting to write back, and dispatch is not
- // unblocking, then there is no internal activity for the IEW stage.
- if (_status == Active && !instQueue.hasReadyInsts() &&
- !ldstQueue.willWB() && !any_unblocking) {
- DPRINTF(IEW, "IEW switching to idle\n");
-
- deactivateStage();
-
- _status = Inactive;
- } else if (_status == Inactive && (instQueue.hasReadyInsts() ||
- ldstQueue.willWB() ||
- any_unblocking)) {
- // Otherwise there is internal activity. Set to active.
- DPRINTF(IEW, "IEW switching to active\n");
-
- activateStage();
-
- _status = Active;
- }
-}
-
-template <class Impl>
-void
-DefaultIEW<Impl>::resetEntries()
-{
- instQueue.resetEntries();
- ldstQueue.resetEntries();
-}
-
-template <class Impl>
-void
-DefaultIEW<Impl>::readStallSignals(unsigned tid)
-{
- if (fromCommit->commitBlock[tid]) {
- stalls[tid].commit = true;
- }
-
- if (fromCommit->commitUnblock[tid]) {
- assert(stalls[tid].commit);
- stalls[tid].commit = false;
- }
-}
-
-template <class Impl>
-bool
-DefaultIEW<Impl>::checkStall(unsigned tid)
-{
- bool ret_val(false);
-
- if (stalls[tid].commit) {
- DPRINTF(IEW,"[tid:%i]: Stall from Commit stage detected.\n",tid);
- ret_val = true;
- } else if (instQueue.isFull(tid)) {
- DPRINTF(IEW,"[tid:%i]: Stall: IQ is full.\n",tid);
- ret_val = true;
- } else if (ldstQueue.isFull(tid)) {
- DPRINTF(IEW,"[tid:%i]: Stall: LSQ is full\n",tid);
-
- if (ldstQueue.numLoads(tid) > 0 ) {
-
- DPRINTF(IEW,"[tid:%i]: LSQ oldest load: [sn:%i] \n",
- tid,ldstQueue.getLoadHeadSeqNum(tid));
- }
-
- if (ldstQueue.numStores(tid) > 0) {
-
- DPRINTF(IEW,"[tid:%i]: LSQ oldest store: [sn:%i] \n",
- tid,ldstQueue.getStoreHeadSeqNum(tid));
- }
-
- ret_val = true;
- } else if (ldstQueue.isStalled(tid)) {
- DPRINTF(IEW,"[tid:%i]: Stall: LSQ stall detected.\n",tid);
- ret_val = true;
- }
-
- return ret_val;
-}
-
-template <class Impl>
-void
-DefaultIEW<Impl>::checkSignalsAndUpdate(unsigned tid)
-{
- // Check if there's a squash signal, squash if there is
- // Check stall signals, block if there is.
- // If status was Blocked
- // if so then go to unblocking
- // If status was Squashing
- // check if squashing is not high. Switch to running this cycle.
-
- readStallSignals(tid);
-
- if (fromCommit->commitInfo[tid].squash) {
- squash(tid);
-
- if (dispatchStatus[tid] == Blocked ||
- dispatchStatus[tid] == Unblocking) {
- toRename->iewUnblock[tid] = true;
- wroteToTimeBuffer = true;
- }
-
- dispatchStatus[tid] = Squashing;
-
- fetchRedirect[tid] = false;
- return;
- }
-
- if (fromCommit->commitInfo[tid].robSquashing) {
- DPRINTF(IEW, "[tid:%i]: ROB is still squashing.\n");
-
- dispatchStatus[tid] = Squashing;
-
- return;
- }
-
- if (checkStall(tid)) {
- block(tid);
- dispatchStatus[tid] = Blocked;
- return;
- }
-
- if (dispatchStatus[tid] == Blocked) {
- // Status from previous cycle was blocked, but there are no more stall
- // conditions. Switch over to unblocking.
- DPRINTF(IEW, "[tid:%i]: Done blocking, switching to unblocking.\n",
- tid);
-
- dispatchStatus[tid] = Unblocking;
-
- unblock(tid);
-
- return;
- }
-
- if (dispatchStatus[tid] == Squashing) {
- // Switch status to running if rename isn't being told to block or
- // squash this cycle.
- DPRINTF(IEW, "[tid:%i]: Done squashing, switching to running.\n",
- tid);
-
- dispatchStatus[tid] = Running;
-
- return;
- }
-}
-
-template <class Impl>
-void
-DefaultIEW<Impl>::sortInsts()
-{
- int insts_from_rename = fromRename->size;
-#ifdef DEBUG
- for (int i = 0; i < numThreads; i++)
- assert(insts[i].empty());
-#endif
- for (int i = 0; i < insts_from_rename; ++i) {
- insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]);
- }
-}
-
-template <class Impl>
-void
-DefaultIEW<Impl>::wakeCPU()
-{
- cpu->wakeCPU();
-}
-
-template <class Impl>
-void
-DefaultIEW<Impl>::activityThisCycle()
-{
- DPRINTF(Activity, "Activity this cycle.\n");
- cpu->activityThisCycle();
-}
-
-template <class Impl>
-inline void
-DefaultIEW<Impl>::activateStage()
-{
- DPRINTF(Activity, "Activating stage.\n");
- cpu->activateStage(FullCPU::IEWIdx);
-}
-
-template <class Impl>
-inline void
-DefaultIEW<Impl>::deactivateStage()
-{
- DPRINTF(Activity, "Deactivating stage.\n");
- cpu->deactivateStage(FullCPU::IEWIdx);
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::dispatch(unsigned tid)
-{
- // If status is Running or idle,
- // call dispatchInsts()
- // If status is Unblocking,
- // buffer any instructions coming from rename
- // continue trying to empty skid buffer
- // check if stall conditions have passed
-
- if (dispatchStatus[tid] == Blocked) {
- ++iewBlockCycles;
-
- } else if (dispatchStatus[tid] == Squashing) {
- ++iewSquashCycles;
- }
-
- // Dispatch should try to dispatch as many instructions as its bandwidth
- // will allow, as long as it is not currently blocked.
- if (dispatchStatus[tid] == Running ||
- dispatchStatus[tid] == Idle) {
- DPRINTF(IEW, "[tid:%i] Not blocked, so attempting to run "
- "dispatch.\n", tid);
-
- dispatchInsts(tid);
- } else if (dispatchStatus[tid] == Unblocking) {
- // Make sure that the skid buffer has something in it if the
- // status is unblocking.
- assert(!skidsEmpty());
-
- // If the status was unblocking, then instructions from the skid
- // buffer were used. Remove those instructions and handle
- // the rest of unblocking.
- dispatchInsts(tid);
-
- ++iewUnblockCycles;
-
- if (validInstsFromRename() && dispatchedAllInsts) {
- // Add the current inputs to the skid buffer so they can be
- // reprocessed when this stage unblocks.
- skidInsert(tid);
- }
-
- unblock(tid);
- }
-}
-
-template <class Impl>
-void
-DefaultIEW<Impl>::dispatchInsts(unsigned tid)
-{
- dispatchedAllInsts = true;
-
- // Obtain instructions from skid buffer if unblocking, or queue from rename
- // otherwise.
- std::queue<DynInstPtr> &insts_to_dispatch =
- dispatchStatus[tid] == Unblocking ?
- skidBuffer[tid] : insts[tid];
-
- int insts_to_add = insts_to_dispatch.size();
-
- DynInstPtr inst;
- bool add_to_iq = false;
- int dis_num_inst = 0;
-
- // Loop through the instructions, putting them in the instruction
- // queue.
- for ( ; dis_num_inst < insts_to_add &&
- dis_num_inst < issueReadWidth;
- ++dis_num_inst)
- {
- inst = insts_to_dispatch.front();
-
- if (dispatchStatus[tid] == Unblocking) {
- DPRINTF(IEW, "[tid:%i]: Issue: Examining instruction from skid "
- "buffer\n", tid);
- }
-
- // Make sure there's a valid instruction there.
- assert(inst);
-
- DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %#x [sn:%lli] [tid:%i] to "
- "IQ.\n",
- tid, inst->readPC(), inst->seqNum, inst->threadNumber);
-
- // Be sure to mark these instructions as ready so that the
- // commit stage can go ahead and execute them, and mark
- // them as issued so the IQ doesn't reprocess them.
-
- // Check for squashed instructions.
- if (inst->isSquashed()) {
- DPRINTF(IEW, "[tid:%i]: Issue: Squashed instruction encountered, "
- "not adding to IQ.\n", tid);
-
- ++iewDispSquashedInsts;
-
- insts_to_dispatch.pop();
-
- //Tell Rename That An Instruction has been processed
- if (inst->isLoad() || inst->isStore()) {
- toRename->iewInfo[tid].dispatchedToLSQ++;
- }
- toRename->iewInfo[tid].dispatched++;
-
- continue;
- }
-
- // Check for full conditions.
- if (instQueue.isFull(tid)) {
- DPRINTF(IEW, "[tid:%i]: Issue: IQ has become full.\n", tid);
-
- // Call function to start blocking.
- block(tid);
-
- // Set unblock to false. Special case where we are using
- // skidbuffer (unblocking) instructions but then we still
- // get full in the IQ.
- toRename->iewUnblock[tid] = false;
-
- dispatchedAllInsts = false;
-
- ++iewIQFullEvents;
- break;
- } else if (ldstQueue.isFull(tid)) {
- DPRINTF(IEW, "[tid:%i]: Issue: LSQ has become full.\n",tid);
-
- // Call function to start blocking.
- block(tid);
-
- // Set unblock to false. Special case where we are using
- // skidbuffer (unblocking) instructions but then we still
- // get full in the IQ.
- toRename->iewUnblock[tid] = false;
-
- dispatchedAllInsts = false;
-
- ++iewLSQFullEvents;
- break;
- }
-
- // Otherwise issue the instruction just fine.
- if (inst->isLoad()) {
- DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction "
- "encountered, adding to LSQ.\n", tid);
-
- // Reserve a spot in the load store queue for this
- // memory access.
- ldstQueue.insertLoad(inst);
-
- ++iewDispLoadInsts;
-
- add_to_iq = true;
-
- toRename->iewInfo[tid].dispatchedToLSQ++;
- } else if (inst->isStore()) {
- DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction "
- "encountered, adding to LSQ.\n", tid);
-
- ldstQueue.insertStore(inst);
-
- ++iewDispStoreInsts;
-
- if (inst->isStoreConditional()) {
- // Store conditionals need to be set as "canCommit()"
- // so that commit can process them when they reach the
- // head of commit.
- // @todo: This is somewhat specific to Alpha.
- inst->setCanCommit();
- instQueue.insertNonSpec(inst);
- add_to_iq = false;
-
- ++iewDispNonSpecInsts;
- } else {
- add_to_iq = true;
- }
-
- toRename->iewInfo[tid].dispatchedToLSQ++;
-#if FULL_SYSTEM
- } else if (inst->isMemBarrier() || inst->isWriteBarrier()) {
- // Same as non-speculative stores.
- inst->setCanCommit();
- instQueue.insertBarrier(inst);
- add_to_iq = false;
-#endif
- } else if (inst->isNonSpeculative()) {
- DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction "
- "encountered, skipping.\n", tid);
-
- // Same as non-speculative stores.
- inst->setCanCommit();
-
- // Specifically insert it as nonspeculative.
- instQueue.insertNonSpec(inst);
-
- ++iewDispNonSpecInsts;
-
- add_to_iq = false;
- } else if (inst->isNop()) {
- DPRINTF(IEW, "[tid:%i]: Issue: Nop instruction encountered, "
- "skipping.\n", tid);
-
- inst->setIssued();
- inst->setExecuted();
- inst->setCanCommit();
-
- instQueue.recordProducer(inst);
-
- exeNop[tid]++;
-
- add_to_iq = false;
- } else if (inst->isExecuted()) {
- assert(0 && "Instruction shouldn't be executed.\n");
- DPRINTF(IEW, "Issue: Executed branch encountered, "
- "skipping.\n");
-
- inst->setIssued();
- inst->setCanCommit();
-
- instQueue.recordProducer(inst);
-
- add_to_iq = false;
- } else {
- add_to_iq = true;
- }
-
- // If the instruction queue is not full, then add the
- // instruction.
- if (add_to_iq) {
- instQueue.insert(inst);
- }
-
- insts_to_dispatch.pop();
-
- toRename->iewInfo[tid].dispatched++;
-
- ++iewDispatchedInsts;
- }
-
- if (!insts_to_dispatch.empty()) {
- DPRINTF(IEW,"[tid:%i]: Issue: Bandwidth Full. Blocking.\n");
- block(tid);
- toRename->iewUnblock[tid] = false;
- }
-
- if (dispatchStatus[tid] == Idle && dis_num_inst) {
- dispatchStatus[tid] = Running;
-
- updatedQueues = true;
- }
-
- dis_num_inst = 0;
-}
-
-template <class Impl>
-void
-DefaultIEW<Impl>::printAvailableInsts()
-{
- int inst = 0;
-
- cout << "Available Instructions: ";
-
- while (fromIssue->insts[inst]) {
-
- if (inst%3==0) cout << "\n\t";
-
- cout << "PC: " << fromIssue->insts[inst]->readPC()
- << " TN: " << fromIssue->insts[inst]->threadNumber
- << " SN: " << fromIssue->insts[inst]->seqNum << " | ";
-
- inst++;
-
- }
-
- cout << "\n";
-}
-
-template <class Impl>
-void
-DefaultIEW<Impl>::executeInsts()
-{
- wbNumInst = 0;
- wbCycle = 0;
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
- fetchRedirect[tid] = false;
- }
-
-#if 0
- printAvailableInsts();
-#endif
-
- // Execute/writeback any instructions that are available.
- int insts_to_execute = fromIssue->size;
- int inst_num = 0;
- for (; inst_num < insts_to_execute;
- ++inst_num) {
-
- DPRINTF(IEW, "Execute: Executing instructions from IQ.\n");
-
- DynInstPtr inst = instQueue.getInstToExecute();
-
- DPRINTF(IEW, "Execute: Processing PC %#x, [tid:%i] [sn:%i].\n",
- inst->readPC(), inst->threadNumber,inst->seqNum);
-
- // Check if the instruction is squashed; if so then skip it
- if (inst->isSquashed()) {
- DPRINTF(IEW, "Execute: Instruction was squashed.\n");
-
- // Consider this instruction executed so that commit can go
- // ahead and retire the instruction.
- inst->setExecuted();
-
- // Not sure if I should set this here or just let commit try to
- // commit any squashed instructions. I like the latter a bit more.
- inst->setCanCommit();
-
- ++iewExecSquashedInsts;
-
- continue;
- }
-
- Fault fault = NoFault;
-
- // Execute instruction.
- // Note that if the instruction faults, it will be handled
- // at the commit stage.
- if (inst->isMemRef() &&
- (!inst->isDataPrefetch() && !inst->isInstPrefetch())) {
- DPRINTF(IEW, "Execute: Calculating address for memory "
- "reference.\n");
-
- // Tell the LDSTQ to execute this instruction (if it is a load).
- if (inst->isLoad()) {
- // Loads will mark themselves as executed, and their writeback
- // event adds the instruction to the queue to commit
- fault = ldstQueue.executeLoad(inst);
- } else if (inst->isStore()) {
- ldstQueue.executeStore(inst);
-
- // If the store had a fault then it may not have a mem req
- if (inst->req && !(inst->req->flags & LOCKED)) {
- inst->setExecuted();
-
- instToCommit(inst);
- }
-
- // Store conditionals will mark themselves as
- // executed, and their writeback event will add the
- // instruction to the queue to commit.
- } else {
- panic("Unexpected memory type!\n");
- }
-
- } else {
- inst->execute();
-
- inst->setExecuted();
-
- instToCommit(inst);
- }
-
- updateExeInstStats(inst);
-
- // Check if branch prediction was correct, if not then we need
- // to tell commit to squash in flight instructions. Only
- // handle this if there hasn't already been something that
- // redirects fetch in this group of instructions.
-
- // This probably needs to prioritize the redirects if a different
- // scheduler is used. Currently the scheduler schedules the oldest
- // instruction first, so the branch resolution order will be correct.
- unsigned tid = inst->threadNumber;
-
- if (!fetchRedirect[tid]) {
-
- if (inst->mispredicted()) {
- fetchRedirect[tid] = true;
-
- DPRINTF(IEW, "Execute: Branch mispredict detected.\n");
- DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n",
- inst->nextPC);
-
- // If incorrect, then signal the ROB that it must be squashed.
- squashDueToBranch(inst, tid);
-
- if (inst->predTaken()) {
- predictedTakenIncorrect++;
- } else {
- predictedNotTakenIncorrect++;
- }
- } else if (ldstQueue.violation(tid)) {
- fetchRedirect[tid] = true;
-
- // If there was an ordering violation, then get the
- // DynInst that caused the violation. Note that this
- // clears the violation signal.
- DynInstPtr violator;
- violator = ldstQueue.getMemDepViolator(tid);
-
- DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: "
- "%#x, inst PC: %#x. Addr is: %#x.\n",
- violator->readPC(), inst->readPC(), inst->physEffAddr);
-
- // Tell the instruction queue that a violation has occured.
- instQueue.violation(inst, violator);
-
- // Squash.
- squashDueToMemOrder(inst,tid);
-
- ++memOrderViolationEvents;
- } else if (ldstQueue.loadBlocked(tid) &&
- !ldstQueue.isLoadBlockedHandled(tid)) {
- fetchRedirect[tid] = true;
-
- DPRINTF(IEW, "Load operation couldn't execute because the "
- "memory system is blocked. PC: %#x [sn:%lli]\n",
- inst->readPC(), inst->seqNum);
-
- squashDueToMemBlocked(inst, tid);
- }
- }
- }
-
- // Update and record activity if we processed any instructions.
- if (inst_num) {
- if (exeStatus == Idle) {
- exeStatus = Running;
- }
-
- updatedQueues = true;
-
- cpu->activityThisCycle();
- }
-
- // Need to reset this in case a writeback event needs to write into the
- // iew queue. That way the writeback event will write into the correct
- // spot in the queue.
- wbNumInst = 0;
-}
-
-template <class Impl>
-void
-DefaultIEW<Impl>::writebackInsts()
-{
- // Loop through the head of the time buffer and wake any
- // dependents. These instructions are about to write back. Also
- // mark scoreboard that this instruction is finally complete.
- // Either have IEW have direct access to scoreboard, or have this
- // as part of backwards communication.
- for (int inst_num = 0; inst_num < issueWidth &&
- toCommit->insts[inst_num]; inst_num++) {
- DynInstPtr inst = toCommit->insts[inst_num];
- int tid = inst->threadNumber;
-
- DPRINTF(IEW, "Sending instructions to commit, PC %#x.\n",
- inst->readPC());
-
- iewInstsToCommit[tid]++;
-
- // Some instructions will be sent to commit without having
- // executed because they need commit to handle them.
- // E.g. Uncached loads have not actually executed when they
- // are first sent to commit. Instead commit must tell the LSQ
- // when it's ready to execute the uncached load.
- if (!inst->isSquashed() && inst->isExecuted()) {
- int dependents = instQueue.wakeDependents(inst);
-
- for (int i = 0; i < inst->numDestRegs(); i++) {
- //mark as Ready
- DPRINTF(IEW,"Setting Destination Register %i\n",
- inst->renamedDestRegIdx(i));
- scoreboard->setReg(inst->renamedDestRegIdx(i));
- }
-
- if (dependents) {
- producerInst[tid]++;
- consumerInst[tid]+= dependents;
- }
- writebackCount[tid]++;
- }
- }
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::tick()
-{
- wbNumInst = 0;
- wbCycle = 0;
-
- wroteToTimeBuffer = false;
- updatedQueues = false;
-
- sortInsts();
-
- // Free function units marked as being freed this cycle.
- fuPool->processFreeUnits();
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- // Check stall and squash signals, dispatch any instructions.
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- DPRINTF(IEW,"Issue: Processing [tid:%i]\n",tid);
-
- checkSignalsAndUpdate(tid);
- dispatch(tid);
- }
-
- if (exeStatus != Squashing) {
- executeInsts();
-
- writebackInsts();
-
- // Have the instruction queue try to schedule any ready instructions.
- // (In actuality, this scheduling is for instructions that will
- // be executed next cycle.)
- instQueue.scheduleReadyInsts();
-
- // Also should advance its own time buffers if the stage ran.
- // Not the best place for it, but this works (hopefully).
- issueToExecQueue.advance();
- }
-
- bool broadcast_free_entries = false;
-
- if (updatedQueues || exeStatus == Running || updateLSQNextCycle) {
- exeStatus = Idle;
- updateLSQNextCycle = false;
-
- broadcast_free_entries = true;
- }
-
- // Writeback any stores using any leftover bandwidth.
- ldstQueue.writebackStores();
-
- // Check the committed load/store signals to see if there's a load
- // or store to commit. Also check if it's being told to execute a
- // nonspeculative instruction.
- // This is pretty inefficient...
-
- threads = (*activeThreads).begin();
- while (threads != (*activeThreads).end()) {
- unsigned tid = (*threads++);
-
- DPRINTF(IEW,"Processing [tid:%i]\n",tid);
-
- // Update structures based on instructions committed.
- if (fromCommit->commitInfo[tid].doneSeqNum != 0 &&
- !fromCommit->commitInfo[tid].squash &&
- !fromCommit->commitInfo[tid].robSquashing) {
-
- ldstQueue.commitStores(fromCommit->commitInfo[tid].doneSeqNum,tid);
-
- ldstQueue.commitLoads(fromCommit->commitInfo[tid].doneSeqNum,tid);
-
- updateLSQNextCycle = true;
- instQueue.commit(fromCommit->commitInfo[tid].doneSeqNum,tid);
- }
-
- if (fromCommit->commitInfo[tid].nonSpecSeqNum != 0) {
-
- //DPRINTF(IEW,"NonspecInst from thread %i",tid);
- if (fromCommit->commitInfo[tid].uncached) {
- instQueue.replayMemInst(fromCommit->commitInfo[tid].uncachedLoad);
- } else {
- instQueue.scheduleNonSpec(
- fromCommit->commitInfo[tid].nonSpecSeqNum);
- }
- }
-
- if (broadcast_free_entries) {
- toFetch->iewInfo[tid].iqCount =
- instQueue.getCount(tid);
- toFetch->iewInfo[tid].ldstqCount =
- ldstQueue.getCount(tid);
-
- toRename->iewInfo[tid].usedIQ = true;
- toRename->iewInfo[tid].freeIQEntries =
- instQueue.numFreeEntries();
- toRename->iewInfo[tid].usedLSQ = true;
- toRename->iewInfo[tid].freeLSQEntries =
- ldstQueue.numFreeEntries(tid);
-
- wroteToTimeBuffer = true;
- }
-
- DPRINTF(IEW, "[tid:%i], Dispatch dispatched %i instructions.\n",
- tid, toRename->iewInfo[tid].dispatched);
- }
-
- DPRINTF(IEW, "IQ has %i free entries (Can schedule: %i). "
- "LSQ has %i free entries.\n",
- instQueue.numFreeEntries(), instQueue.hasReadyInsts(),
- ldstQueue.numFreeEntries());
-
- updateStatus();
-
- if (wroteToTimeBuffer) {
- DPRINTF(Activity, "Activity this cycle.\n");
- cpu->activityThisCycle();
- }
-}
-
-template <class Impl>
-void
-DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst)
-{
- int thread_number = inst->threadNumber;
-
- //
- // Pick off the software prefetches
- //
-#ifdef TARGET_ALPHA
- if (inst->isDataPrefetch())
- exeSwp[thread_number]++;
- else
- iewExecutedInsts++;
-#else
- iewExecutedInsts[thread_number]++;
-#endif
-
- //
- // Control operations
- //
- if (inst->isControl())
- exeBranches[thread_number]++;
-
- //
- // Memory operations
- //
- if (inst->isMemRef()) {
- exeRefs[thread_number]++;
-
- if (inst->isLoad()) {
- iewExecLoadInsts[thread_number]++;
- }
- }
-}
diff --git a/cpu/o3/inst_queue.cc b/cpu/o3/inst_queue.cc
deleted file mode 100644
index 95ae2b699..000000000
--- a/cpu/o3/inst_queue.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/o3/alpha_dyn_inst.hh"
-#include "cpu/o3/alpha_impl.hh"
-#include "cpu/o3/inst_queue_impl.hh"
-
-// Force instantiation of InstructionQueue.
-template class InstructionQueue<AlphaSimpleImpl>;
diff --git a/cpu/o3/inst_queue.hh b/cpu/o3/inst_queue.hh
deleted file mode 100644
index 4802cbaf4..000000000
--- a/cpu/o3/inst_queue.hh
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_INST_QUEUE_HH__
-#define __CPU_O3_INST_QUEUE_HH__
-
-#include <list>
-#include <map>
-#include <queue>
-#include <vector>
-
-#include "base/statistics.hh"
-#include "base/timebuf.hh"
-#include "cpu/inst_seq.hh"
-#include "cpu/o3/dep_graph.hh"
-#include "encumbered/cpu/full/op_class.hh"
-#include "sim/host.hh"
-
-class FUPool;
-class MemInterface;
-
-/**
- * A standard instruction queue class. It holds ready instructions, in
- * order, in seperate priority queues to facilitate the scheduling of
- * instructions. The IQ uses a separate linked list to track dependencies.
- * Similar to the rename map and the free list, it expects that
- * floating point registers have their indices start after the integer
- * registers (ie with 96 int and 96 fp registers, regs 0-95 are integer
- * and 96-191 are fp). This remains true even for both logical and
- * physical register indices. The IQ depends on the memory dependence unit to
- * track when memory operations are ready in terms of ordering; register
- * dependencies are tracked normally. Right now the IQ also handles the
- * execution timing; this is mainly to allow back-to-back scheduling without
- * requiring IEW to be able to peek into the IQ. At the end of the execution
- * latency, the instruction is put into the queue to execute, where it will
- * have the execute() function called on it.
- * @todo: Make IQ able to handle multiple FU pools.
- */
-template <class Impl>
-class InstructionQueue
-{
- public:
- //Typedefs from the Impl.
- typedef typename Impl::FullCPU FullCPU;
- typedef typename Impl::DynInstPtr DynInstPtr;
- typedef typename Impl::Params Params;
-
- typedef typename Impl::CPUPol::IEW IEW;
- typedef typename Impl::CPUPol::MemDepUnit MemDepUnit;
- typedef typename Impl::CPUPol::IssueStruct IssueStruct;
- typedef typename Impl::CPUPol::TimeStruct TimeStruct;
-
- // Typedef of iterator through the list of instructions.
- typedef typename std::list<DynInstPtr>::iterator ListIt;
-
- friend class Impl::FullCPU;
-
- /** FU completion event class. */
- class FUCompletion : public Event {
- private:
- /** Executing instruction. */
- DynInstPtr inst;
-
- /** Index of the FU used for executing. */
- int fuIdx;
-
- /** Pointer back to the instruction queue. */
- InstructionQueue<Impl> *iqPtr;
-
- /** Should the FU be added to the list to be freed upon
- * completing this event.
- */
- bool freeFU;
-
- public:
- /** Construct a FU completion event. */
- FUCompletion(DynInstPtr &_inst, int fu_idx,
- InstructionQueue<Impl> *iq_ptr);
-
- virtual void process();
- virtual const char *description();
- void setFreeFU() { freeFU = true; }
- };
-
- /** Constructs an IQ. */
- InstructionQueue(Params *params);
-
- /** Destructs the IQ. */
- ~InstructionQueue();
-
- /** Returns the name of the IQ. */
- std::string name() const;
-
- /** Registers statistics. */
- void regStats();
-
- /** Resets all instruction queue state. */
- void resetState();
-
- /** Sets CPU pointer. */
- void setCPU(FullCPU *_cpu) { cpu = _cpu; }
-
- /** Sets active threads list. */
- void setActiveThreads(std::list<unsigned> *at_ptr);
-
- /** Sets the IEW pointer. */
- void setIEW(IEW *iew_ptr) { iewStage = iew_ptr; }
-
- /** Sets the timer buffer between issue and execute. */
- void setIssueToExecuteQueue(TimeBuffer<IssueStruct> *i2eQueue);
-
- /** Sets the global time buffer. */
- void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
-
- /** Switches out the instruction queue. */
- void switchOut();
-
- /** Takes over execution from another CPU's thread. */
- void takeOverFrom();
-
- /** Returns if the IQ is switched out. */
- bool isSwitchedOut() { return switchedOut; }
-
- /** Number of entries needed for given amount of threads. */
- int entryAmount(int num_threads);
-
- /** Resets max entries for all threads. */
- void resetEntries();
-
- /** Returns total number of free entries. */
- unsigned numFreeEntries();
-
- /** Returns number of free entries for a thread. */
- unsigned numFreeEntries(unsigned tid);
-
- /** Returns whether or not the IQ is full. */
- bool isFull();
-
- /** Returns whether or not the IQ is full for a specific thread. */
- bool isFull(unsigned tid);
-
- /** Returns if there are any ready instructions in the IQ. */
- bool hasReadyInsts();
-
- /** Inserts a new instruction into the IQ. */
- void insert(DynInstPtr &new_inst);
-
- /** Inserts a new, non-speculative instruction into the IQ. */
- void insertNonSpec(DynInstPtr &new_inst);
-
- /** Inserts a memory or write barrier into the IQ to make sure
- * loads and stores are ordered properly.
- */
- void insertBarrier(DynInstPtr &barr_inst);
-
- /** Returns the oldest scheduled instruction, and removes it from
- * the list of instructions waiting to execute.
- */
- DynInstPtr getInstToExecute();
-
- /**
- * Records the instruction as the producer of a register without
- * adding it to the rest of the IQ.
- */
- void recordProducer(DynInstPtr &inst)
- { addToProducers(inst); }
-
- /** Process FU completion event. */
- void processFUCompletion(DynInstPtr &inst, int fu_idx);
-
- /**
- * Schedules ready instructions, adding the ready ones (oldest first) to
- * the queue to execute.
- */
- void scheduleReadyInsts();
-
- /** Schedules a single specific non-speculative instruction. */
- void scheduleNonSpec(const InstSeqNum &inst);
-
- /**
- * Commits all instructions up to and including the given sequence number,
- * for a specific thread.
- */
- void commit(const InstSeqNum &inst, unsigned tid = 0);
-
- /** Wakes all dependents of a completed instruction. */
- int wakeDependents(DynInstPtr &completed_inst);
-
- /** Adds a ready memory instruction to the ready list. */
- void addReadyMemInst(DynInstPtr &ready_inst);
-
- /**
- * Reschedules a memory instruction. It will be ready to issue once
- * replayMemInst() is called.
- */
- void rescheduleMemInst(DynInstPtr &resched_inst);
-
- /** Replays a memory instruction. It must be rescheduled first. */
- void replayMemInst(DynInstPtr &replay_inst);
-
- /** Completes a memory operation. */
- void completeMemInst(DynInstPtr &completed_inst);
-
- /** Indicates an ordering violation between a store and a load. */
- void violation(DynInstPtr &store, DynInstPtr &faulting_load);
-
- /**
- * Squashes instructions for a thread. Squashing information is obtained
- * from the time buffer.
- */
- void squash(unsigned tid);
-
- /** Returns the number of used entries for a thread. */
- unsigned getCount(unsigned tid) { return count[tid]; };
-
- /** Debug function to print all instructions. */
- void printInsts();
-
- private:
- /** Does the actual squashing. */
- void doSquash(unsigned tid);
-
- /////////////////////////
- // Various pointers
- /////////////////////////
-
- /** Pointer to the CPU. */
- FullCPU *cpu;
-
- /** Cache interface. */
- MemInterface *dcacheInterface;
-
- /** Pointer to IEW stage. */
- IEW *iewStage;
-
- /** The memory dependence unit, which tracks/predicts memory dependences
- * between instructions.
- */
- MemDepUnit memDepUnit[Impl::MaxThreads];
-
- /** The queue to the execute stage. Issued instructions will be written
- * into it.
- */
- TimeBuffer<IssueStruct> *issueToExecuteQueue;
-
- /** The backwards time buffer. */
- TimeBuffer<TimeStruct> *timeBuffer;
-
- /** Wire to read information from timebuffer. */
- typename TimeBuffer<TimeStruct>::wire fromCommit;
-
- /** Function unit pool. */
- FUPool *fuPool;
-
- //////////////////////////////////////
- // Instruction lists, ready queues, and ordering
- //////////////////////////////////////
-
- /** List of all the instructions in the IQ (some of which may be issued). */
- std::list<DynInstPtr> instList[Impl::MaxThreads];
-
- /** List of instructions that are ready to be executed. */
- std::list<DynInstPtr> instsToExecute;
-
- /**
- * Struct for comparing entries to be added to the priority queue.
- * This gives reverse ordering to the instructions in terms of
- * sequence numbers: the instructions with smaller sequence
- * numbers (and hence are older) will be at the top of the
- * priority queue.
- */
- struct pqCompare {
- bool operator() (const DynInstPtr &lhs, const DynInstPtr &rhs) const
- {
- return lhs->seqNum > rhs->seqNum;
- }
- };
-
- typedef std::priority_queue<DynInstPtr, std::vector<DynInstPtr>, pqCompare>
- ReadyInstQueue;
-
- /** List of ready instructions, per op class. They are separated by op
- * class to allow for easy mapping to FUs.
- */
- ReadyInstQueue readyInsts[Num_OpClasses];
-
- /** List of non-speculative instructions that will be scheduled
- * once the IQ gets a signal from commit. While it's redundant to
- * have the key be a part of the value (the sequence number is stored
- * inside of DynInst), when these instructions are woken up only
- * the sequence number will be available. Thus it is most efficient to be
- * able to search by the sequence number alone.
- */
- std::map<InstSeqNum, DynInstPtr> nonSpecInsts;
-
- typedef typename std::map<InstSeqNum, DynInstPtr>::iterator NonSpecMapIt;
-
- /** Entry for the list age ordering by op class. */
- struct ListOrderEntry {
- OpClass queueType;
- InstSeqNum oldestInst;
- };
-
- /** List that contains the age order of the oldest instruction of each
- * ready queue. Used to select the oldest instruction available
- * among op classes.
- * @todo: Might be better to just move these entries around instead
- * of creating new ones every time the position changes due to an
- * instruction issuing. Not sure std::list supports this.
- */
- std::list<ListOrderEntry> listOrder;
-
- typedef typename std::list<ListOrderEntry>::iterator ListOrderIt;
-
- /** Tracks if each ready queue is on the age order list. */
- bool queueOnList[Num_OpClasses];
-
- /** Iterators of each ready queue. Points to their spot in the age order
- * list.
- */
- ListOrderIt readyIt[Num_OpClasses];
-
- /** Add an op class to the age order list. */
- void addToOrderList(OpClass op_class);
-
- /**
- * Called when the oldest instruction has been removed from a ready queue;
- * this places that ready queue into the proper spot in the age order list.
- */
- void moveToYoungerInst(ListOrderIt age_order_it);
-
- DependencyGraph<DynInstPtr> dependGraph;
-
- //////////////////////////////////////
- // Various parameters
- //////////////////////////////////////
-
- /** IQ Resource Sharing Policy */
- enum IQPolicy {
- Dynamic,
- Partitioned,
- Threshold
- };
-
- /** IQ sharing policy for SMT. */
- IQPolicy iqPolicy;
-
- /** Number of Total Threads*/
- unsigned numThreads;
-
- /** Pointer to list of active threads. */
- std::list<unsigned> *activeThreads;
-
- /** Per Thread IQ count */
- unsigned count[Impl::MaxThreads];
-
- /** Max IQ Entries Per Thread */
- unsigned maxEntries[Impl::MaxThreads];
-
- /** Number of free IQ entries left. */
- unsigned freeEntries;
-
- /** The number of entries in the instruction queue. */
- unsigned numEntries;
-
- /** The total number of instructions that can be issued in one cycle. */
- unsigned totalWidth;
-
- /** The number of physical registers in the CPU. */
- unsigned numPhysRegs;
-
- /** The number of physical integer registers in the CPU. */
- unsigned numPhysIntRegs;
-
- /** The number of floating point registers in the CPU. */
- unsigned numPhysFloatRegs;
-
- /** Delay between commit stage and the IQ.
- * @todo: Make there be a distinction between the delays within IEW.
- */
- unsigned commitToIEWDelay;
-
- /** Is the IQ switched out. */
- bool switchedOut;
-
- /** The sequence number of the squashed instruction. */
- InstSeqNum squashedSeqNum[Impl::MaxThreads];
-
- /** A cache of the recently woken registers. It is 1 if the register
- * has been woken up recently, and 0 if the register has been added
- * to the dependency graph and has not yet received its value. It
- * is basically a secondary scoreboard, and should pretty much mirror
- * the scoreboard that exists in the rename map.
- */
- std::vector<bool> regScoreboard;
-
- /** Adds an instruction to the dependency graph, as a consumer. */
- bool addToDependents(DynInstPtr &new_inst);
-
- /** Adds an instruction to the dependency graph, as a producer. */
- void addToProducers(DynInstPtr &new_inst);
-
- /** Moves an instruction to the ready queue if it is ready. */
- void addIfReady(DynInstPtr &inst);
-
- /** Debugging function to count how many entries are in the IQ. It does
- * a linear walk through the instructions, so do not call this function
- * during normal execution.
- */
- int countInsts();
-
- /** Debugging function to dump all the list sizes, as well as print
- * out the list of nonspeculative instructions. Should not be used
- * in any other capacity, but it has no harmful sideaffects.
- */
- void dumpLists();
-
- /** Debugging function to dump out all instructions that are in the
- * IQ.
- */
- void dumpInsts();
-
- /** Stat for number of instructions added. */
- Stats::Scalar<> iqInstsAdded;
- /** Stat for number of non-speculative instructions added. */
- Stats::Scalar<> iqNonSpecInstsAdded;
-
- Stats::Scalar<> iqInstsIssued;
- /** Stat for number of integer instructions issued. */
- Stats::Scalar<> iqIntInstsIssued;
- /** Stat for number of floating point instructions issued. */
- Stats::Scalar<> iqFloatInstsIssued;
- /** Stat for number of branch instructions issued. */
- Stats::Scalar<> iqBranchInstsIssued;
- /** Stat for number of memory instructions issued. */
- Stats::Scalar<> iqMemInstsIssued;
- /** Stat for number of miscellaneous instructions issued. */
- Stats::Scalar<> iqMiscInstsIssued;
- /** Stat for number of squashed instructions that were ready to issue. */
- Stats::Scalar<> iqSquashedInstsIssued;
- /** Stat for number of squashed instructions examined when squashing. */
- Stats::Scalar<> iqSquashedInstsExamined;
- /** Stat for number of squashed instruction operands examined when
- * squashing.
- */
- Stats::Scalar<> iqSquashedOperandsExamined;
- /** Stat for number of non-speculative instructions removed due to a squash.
- */
- Stats::Scalar<> iqSquashedNonSpecRemoved;
-
- /** Distribution of number of instructions in the queue. */
- Stats::VectorDistribution<> queueResDist;
- /** Distribution of the number of instructions issued. */
- Stats::Distribution<> numIssuedDist;
- /** Distribution of the cycles it takes to issue an instruction. */
- Stats::VectorDistribution<> issueDelayDist;
-
- /** Number of times an instruction could not be issued because a
- * FU was busy.
- */
- Stats::Vector<> statFuBusy;
-// Stats::Vector<> dist_unissued;
- /** Stat for total number issued for each instruction type. */
- Stats::Vector2d<> statIssuedInstType;
-
- /** Number of instructions issued per cycle. */
- Stats::Formula issueRate;
-// Stats::Formula issue_stores;
-// Stats::Formula issue_op_rate;
- /** Number of times the FU was busy. */
- Stats::Vector<> fuBusy;
- /** Number of times the FU was busy per instruction issued. */
- Stats::Formula fuBusyRate;
-};
-
-#endif //__CPU_O3_INST_QUEUE_HH__
diff --git a/cpu/o3/inst_queue_impl.hh b/cpu/o3/inst_queue_impl.hh
deleted file mode 100644
index d677a259c..000000000
--- a/cpu/o3/inst_queue_impl.hh
+++ /dev/null
@@ -1,1402 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <limits>
-#include <vector>
-
-#include "sim/root.hh"
-
-#include "cpu/o3/fu_pool.hh"
-#include "cpu/o3/inst_queue.hh"
-
-using namespace std;
-
-template <class Impl>
-InstructionQueue<Impl>::FUCompletion::FUCompletion(DynInstPtr &_inst,
- int fu_idx,
- InstructionQueue<Impl> *iq_ptr)
- : Event(&mainEventQueue, Stat_Event_Pri),
- inst(_inst), fuIdx(fu_idx), iqPtr(iq_ptr), freeFU(false)
-{
- this->setFlags(Event::AutoDelete);
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::FUCompletion::process()
-{
- iqPtr->processFUCompletion(inst, freeFU ? fuIdx : -1);
- inst = NULL;
-}
-
-
-template <class Impl>
-const char *
-InstructionQueue<Impl>::FUCompletion::description()
-{
- return "Functional unit completion event";
-}
-
-template <class Impl>
-InstructionQueue<Impl>::InstructionQueue(Params *params)
- : dcacheInterface(params->dcacheInterface),
- fuPool(params->fuPool),
- numEntries(params->numIQEntries),
- totalWidth(params->issueWidth),
- numPhysIntRegs(params->numPhysIntRegs),
- numPhysFloatRegs(params->numPhysFloatRegs),
- commitToIEWDelay(params->commitToIEWDelay)
-{
- assert(fuPool);
-
- switchedOut = false;
-
- numThreads = params->numberOfThreads;
-
- // Set the number of physical registers as the number of int + float
- numPhysRegs = numPhysIntRegs + numPhysFloatRegs;
-
- DPRINTF(IQ, "There are %i physical registers.\n", numPhysRegs);
-
- //Create an entry for each physical register within the
- //dependency graph.
- dependGraph.resize(numPhysRegs);
-
- // Resize the register scoreboard.
- regScoreboard.resize(numPhysRegs);
-
- //Initialize Mem Dependence Units
- for (int i = 0; i < numThreads; i++) {
- memDepUnit[i].init(params,i);
- memDepUnit[i].setIQ(this);
- }
-
- resetState();
-
- string policy = params->smtIQPolicy;
-
- //Convert string to lowercase
- std::transform(policy.begin(), policy.end(), policy.begin(),
- (int(*)(int)) tolower);
-
- //Figure out resource sharing policy
- if (policy == "dynamic") {
- iqPolicy = Dynamic;
-
- //Set Max Entries to Total ROB Capacity
- for (int i = 0; i < numThreads; i++) {
- maxEntries[i] = numEntries;
- }
-
- } else if (policy == "partitioned") {
- iqPolicy = Partitioned;
-
- //@todo:make work if part_amt doesnt divide evenly.
- int part_amt = numEntries / numThreads;
-
- //Divide ROB up evenly
- for (int i = 0; i < numThreads; i++) {
- maxEntries[i] = part_amt;
- }
-
- DPRINTF(Fetch, "IQ sharing policy set to Partitioned:"
- "%i entries per thread.\n",part_amt);
-
- } else if (policy == "threshold") {
- iqPolicy = Threshold;
-
- double threshold = (double)params->smtIQThreshold / 100;
-
- int thresholdIQ = (int)((double)threshold * numEntries);
-
- //Divide up by threshold amount
- for (int i = 0; i < numThreads; i++) {
- maxEntries[i] = thresholdIQ;
- }
-
- DPRINTF(Fetch, "IQ sharing policy set to Threshold:"
- "%i entries per thread.\n",thresholdIQ);
- } else {
- assert(0 && "Invalid IQ Sharing Policy.Options Are:{Dynamic,"
- "Partitioned, Threshold}");
- }
-}
-
-template <class Impl>
-InstructionQueue<Impl>::~InstructionQueue()
-{
- dependGraph.reset();
-#ifdef DEBUG
- cprintf("Nodes traversed: %i, removed: %i\n",
- dependGraph.nodesTraversed, dependGraph.nodesRemoved);
-#endif
-}
-
-template <class Impl>
-std::string
-InstructionQueue<Impl>::name() const
-{
- return cpu->name() + ".iq";
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::regStats()
-{
- using namespace Stats;
- iqInstsAdded
- .name(name() + ".iqInstsAdded")
- .desc("Number of instructions added to the IQ (excludes non-spec)")
- .prereq(iqInstsAdded);
-
- iqNonSpecInstsAdded
- .name(name() + ".iqNonSpecInstsAdded")
- .desc("Number of non-speculative instructions added to the IQ")
- .prereq(iqNonSpecInstsAdded);
-
- iqInstsIssued
- .name(name() + ".iqInstsIssued")
- .desc("Number of instructions issued")
- .prereq(iqInstsIssued);
-
- iqIntInstsIssued
- .name(name() + ".iqIntInstsIssued")
- .desc("Number of integer instructions issued")
- .prereq(iqIntInstsIssued);
-
- iqFloatInstsIssued
- .name(name() + ".iqFloatInstsIssued")
- .desc("Number of float instructions issued")
- .prereq(iqFloatInstsIssued);
-
- iqBranchInstsIssued
- .name(name() + ".iqBranchInstsIssued")
- .desc("Number of branch instructions issued")
- .prereq(iqBranchInstsIssued);
-
- iqMemInstsIssued
- .name(name() + ".iqMemInstsIssued")
- .desc("Number of memory instructions issued")
- .prereq(iqMemInstsIssued);
-
- iqMiscInstsIssued
- .name(name() + ".iqMiscInstsIssued")
- .desc("Number of miscellaneous instructions issued")
- .prereq(iqMiscInstsIssued);
-
- iqSquashedInstsIssued
- .name(name() + ".iqSquashedInstsIssued")
- .desc("Number of squashed instructions issued")
- .prereq(iqSquashedInstsIssued);
-
- iqSquashedInstsExamined
- .name(name() + ".iqSquashedInstsExamined")
- .desc("Number of squashed instructions iterated over during squash;"
- " mainly for profiling")
- .prereq(iqSquashedInstsExamined);
-
- iqSquashedOperandsExamined
- .name(name() + ".iqSquashedOperandsExamined")
- .desc("Number of squashed operands that are examined and possibly "
- "removed from graph")
- .prereq(iqSquashedOperandsExamined);
-
- iqSquashedNonSpecRemoved
- .name(name() + ".iqSquashedNonSpecRemoved")
- .desc("Number of squashed non-spec instructions that were removed")
- .prereq(iqSquashedNonSpecRemoved);
-
- queueResDist
- .init(Num_OpClasses, 0, 99, 2)
- .name(name() + ".IQ:residence:")
- .desc("cycles from dispatch to issue")
- .flags(total | pdf | cdf )
- ;
- for (int i = 0; i < Num_OpClasses; ++i) {
- queueResDist.subname(i, opClassStrings[i]);
- }
- numIssuedDist
- .init(0,totalWidth,1)
- .name(name() + ".ISSUE:issued_per_cycle")
- .desc("Number of insts issued each cycle")
- .flags(pdf)
- ;
-/*
- dist_unissued
- .init(Num_OpClasses+2)
- .name(name() + ".ISSUE:unissued_cause")
- .desc("Reason ready instruction not issued")
- .flags(pdf | dist)
- ;
- for (int i=0; i < (Num_OpClasses + 2); ++i) {
- dist_unissued.subname(i, unissued_names[i]);
- }
-*/
- statIssuedInstType
- .init(numThreads,Num_OpClasses)
- .name(name() + ".ISSUE:FU_type")
- .desc("Type of FU issued")
- .flags(total | pdf | dist)
- ;
- statIssuedInstType.ysubnames(opClassStrings);
-
- //
- // How long did instructions for a particular FU type wait prior to issue
- //
-
- issueDelayDist
- .init(Num_OpClasses,0,99,2)
- .name(name() + ".ISSUE:")
- .desc("cycles from operands ready to issue")
- .flags(pdf | cdf)
- ;
-
- for (int i=0; i<Num_OpClasses; ++i) {
- stringstream subname;
- subname << opClassStrings[i] << "_delay";
- issueDelayDist.subname(i, subname.str());
- }
-
- issueRate
- .name(name() + ".ISSUE:rate")
- .desc("Inst issue rate")
- .flags(total)
- ;
- issueRate = iqInstsIssued / cpu->numCycles;
-/*
- issue_stores
- .name(name() + ".ISSUE:stores")
- .desc("Number of stores issued")
- .flags(total)
- ;
- issue_stores = exe_refs - exe_loads;
-*/
-/*
- issue_op_rate
- .name(name() + ".ISSUE:op_rate")
- .desc("Operation issue rate")
- .flags(total)
- ;
- issue_op_rate = issued_ops / numCycles;
-*/
- statFuBusy
- .init(Num_OpClasses)
- .name(name() + ".ISSUE:fu_full")
- .desc("attempts to use FU when none available")
- .flags(pdf | dist)
- ;
- for (int i=0; i < Num_OpClasses; ++i) {
- statFuBusy.subname(i, opClassStrings[i]);
- }
-
- fuBusy
- .init(numThreads)
- .name(name() + ".ISSUE:fu_busy_cnt")
- .desc("FU busy when requested")
- .flags(total)
- ;
-
- fuBusyRate
- .name(name() + ".ISSUE:fu_busy_rate")
- .desc("FU busy rate (busy events/executed inst)")
- .flags(total)
- ;
- fuBusyRate = fuBusy / iqInstsIssued;
-
- for ( int i=0; i < numThreads; i++) {
- // Tell mem dependence unit to reg stats as well.
- memDepUnit[i].regStats();
- }
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::resetState()
-{
- //Initialize thread IQ counts
- for (int i = 0; i <numThreads; i++) {
- count[i] = 0;
- instList[i].clear();
- }
-
- // Initialize the number of free IQ entries.
- freeEntries = numEntries;
-
- // Note that in actuality, the registers corresponding to the logical
- // registers start off as ready. However this doesn't matter for the
- // IQ as the instruction should have been correctly told if those
- // registers are ready in rename. Thus it can all be initialized as
- // unready.
- for (int i = 0; i < numPhysRegs; ++i) {
- regScoreboard[i] = false;
- }
-
- for (int i = 0; i < numThreads; ++i) {
- squashedSeqNum[i] = 0;
- }
-
- for (int i = 0; i < Num_OpClasses; ++i) {
- while (!readyInsts[i].empty())
- readyInsts[i].pop();
- queueOnList[i] = false;
- readyIt[i] = listOrder.end();
- }
- nonSpecInsts.clear();
- listOrder.clear();
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::setActiveThreads(list<unsigned> *at_ptr)
-{
- DPRINTF(IQ, "Setting active threads list pointer.\n");
- activeThreads = at_ptr;
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::setIssueToExecuteQueue(TimeBuffer<IssueStruct> *i2e_ptr)
-{
- DPRINTF(IQ, "Set the issue to execute queue.\n");
- issueToExecuteQueue = i2e_ptr;
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
-{
- DPRINTF(IQ, "Set the time buffer.\n");
- timeBuffer = tb_ptr;
-
- fromCommit = timeBuffer->getWire(-commitToIEWDelay);
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::switchOut()
-{
- resetState();
- dependGraph.reset();
- switchedOut = true;
- for (int i = 0; i < numThreads; ++i) {
- memDepUnit[i].switchOut();
- }
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::takeOverFrom()
-{
- switchedOut = false;
-}
-
-template <class Impl>
-int
-InstructionQueue<Impl>::entryAmount(int num_threads)
-{
- if (iqPolicy == Partitioned) {
- return numEntries / num_threads;
- } else {
- return 0;
- }
-}
-
-
-template <class Impl>
-void
-InstructionQueue<Impl>::resetEntries()
-{
- if (iqPolicy != Dynamic || numThreads > 1) {
- int active_threads = (*activeThreads).size();
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
- list<unsigned>::iterator list_end = (*activeThreads).end();
-
- while (threads != list_end) {
- if (iqPolicy == Partitioned) {
- maxEntries[*threads++] = numEntries / active_threads;
- } else if(iqPolicy == Threshold && active_threads == 1) {
- maxEntries[*threads++] = numEntries;
- }
- }
- }
-}
-
-template <class Impl>
-unsigned
-InstructionQueue<Impl>::numFreeEntries()
-{
- return freeEntries;
-}
-
-template <class Impl>
-unsigned
-InstructionQueue<Impl>::numFreeEntries(unsigned tid)
-{
- return maxEntries[tid] - count[tid];
-}
-
-// Might want to do something more complex if it knows how many instructions
-// will be issued this cycle.
-template <class Impl>
-bool
-InstructionQueue<Impl>::isFull()
-{
- if (freeEntries == 0) {
- return(true);
- } else {
- return(false);
- }
-}
-
-template <class Impl>
-bool
-InstructionQueue<Impl>::isFull(unsigned tid)
-{
- if (numFreeEntries(tid) == 0) {
- return(true);
- } else {
- return(false);
- }
-}
-
-template <class Impl>
-bool
-InstructionQueue<Impl>::hasReadyInsts()
-{
- if (!listOrder.empty()) {
- return true;
- }
-
- for (int i = 0; i < Num_OpClasses; ++i) {
- if (!readyInsts[i].empty()) {
- return true;
- }
- }
-
- return false;
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::insert(DynInstPtr &new_inst)
-{
- // Make sure the instruction is valid
- assert(new_inst);
-
- DPRINTF(IQ, "Adding instruction [sn:%lli] PC %#x to the IQ.\n",
- new_inst->seqNum, new_inst->readPC());
-
- assert(freeEntries != 0);
-
- instList[new_inst->threadNumber].push_back(new_inst);
-
- --freeEntries;
-
- new_inst->setInIQ();
-
- // Look through its source registers (physical regs), and mark any
- // dependencies.
- addToDependents(new_inst);
-
- // Have this instruction set itself as the producer of its destination
- // register(s).
- addToProducers(new_inst);
-
- if (new_inst->isMemRef()) {
- memDepUnit[new_inst->threadNumber].insert(new_inst);
- } else {
- addIfReady(new_inst);
- }
-
- ++iqInstsAdded;
-
- count[new_inst->threadNumber]++;
-
- assert(freeEntries == (numEntries - countInsts()));
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::insertNonSpec(DynInstPtr &new_inst)
-{
- // @todo: Clean up this code; can do it by setting inst as unable
- // to issue, then calling normal insert on the inst.
-
- assert(new_inst);
-
- nonSpecInsts[new_inst->seqNum] = new_inst;
-
- DPRINTF(IQ, "Adding non-speculative instruction [sn:%lli] PC %#x "
- "to the IQ.\n",
- new_inst->seqNum, new_inst->readPC());
-
- assert(freeEntries != 0);
-
- instList[new_inst->threadNumber].push_back(new_inst);
-
- --freeEntries;
-
- new_inst->setInIQ();
-
- // Have this instruction set itself as the producer of its destination
- // register(s).
- addToProducers(new_inst);
-
- // If it's a memory instruction, add it to the memory dependency
- // unit.
- if (new_inst->isMemRef()) {
- memDepUnit[new_inst->threadNumber].insertNonSpec(new_inst);
- }
-
- ++iqNonSpecInstsAdded;
-
- count[new_inst->threadNumber]++;
-
- assert(freeEntries == (numEntries - countInsts()));
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::insertBarrier(DynInstPtr &barr_inst)
-{
- memDepUnit[barr_inst->threadNumber].insertBarrier(barr_inst);
-
- insertNonSpec(barr_inst);
-}
-
-template <class Impl>
-typename Impl::DynInstPtr
-InstructionQueue<Impl>::getInstToExecute()
-{
- assert(!instsToExecute.empty());
- DynInstPtr inst = instsToExecute.front();
- instsToExecute.pop_front();
- return inst;
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::addToOrderList(OpClass op_class)
-{
- assert(!readyInsts[op_class].empty());
-
- ListOrderEntry queue_entry;
-
- queue_entry.queueType = op_class;
-
- queue_entry.oldestInst = readyInsts[op_class].top()->seqNum;
-
- ListOrderIt list_it = listOrder.begin();
- ListOrderIt list_end_it = listOrder.end();
-
- while (list_it != list_end_it) {
- if ((*list_it).oldestInst > queue_entry.oldestInst) {
- break;
- }
-
- list_it++;
- }
-
- readyIt[op_class] = listOrder.insert(list_it, queue_entry);
- queueOnList[op_class] = true;
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::moveToYoungerInst(ListOrderIt list_order_it)
-{
- // Get iterator of next item on the list
- // Delete the original iterator
- // Determine if the next item is either the end of the list or younger
- // than the new instruction. If so, then add in a new iterator right here.
- // If not, then move along.
- ListOrderEntry queue_entry;
- OpClass op_class = (*list_order_it).queueType;
- ListOrderIt next_it = list_order_it;
-
- ++next_it;
-
- queue_entry.queueType = op_class;
- queue_entry.oldestInst = readyInsts[op_class].top()->seqNum;
-
- while (next_it != listOrder.end() &&
- (*next_it).oldestInst < queue_entry.oldestInst) {
- ++next_it;
- }
-
- readyIt[op_class] = listOrder.insert(next_it, queue_entry);
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::processFUCompletion(DynInstPtr &inst, int fu_idx)
-{
- // The CPU could have been sleeping until this op completed (*extremely*
- // long latency op). Wake it if it was. This may be overkill.
- if (isSwitchedOut()) {
- return;
- }
-
- iewStage->wakeCPU();
-
- if (fu_idx > -1)
- fuPool->freeUnitNextCycle(fu_idx);
-
- // @todo: Ensure that these FU Completions happen at the beginning
- // of a cycle, otherwise they could add too many instructions to
- // the queue.
- issueToExecuteQueue->access(0)->size++;
- instsToExecute.push_back(inst);
-}
-
-// @todo: Figure out a better way to remove the squashed items from the
-// lists. Checking the top item of each list to see if it's squashed
-// wastes time and forces jumps.
-template <class Impl>
-void
-InstructionQueue<Impl>::scheduleReadyInsts()
-{
- DPRINTF(IQ, "Attempting to schedule ready instructions from "
- "the IQ.\n");
-
- IssueStruct *i2e_info = issueToExecuteQueue->access(0);
-
- // Have iterator to head of the list
- // While I haven't exceeded bandwidth or reached the end of the list,
- // Try to get a FU that can do what this op needs.
- // If successful, change the oldestInst to the new top of the list, put
- // the queue in the proper place in the list.
- // Increment the iterator.
- // This will avoid trying to schedule a certain op class if there are no
- // FUs that handle it.
- ListOrderIt order_it = listOrder.begin();
- ListOrderIt order_end_it = listOrder.end();
- int total_issued = 0;
-
- while (total_issued < totalWidth &&
- order_it != order_end_it) {
- OpClass op_class = (*order_it).queueType;
-
- assert(!readyInsts[op_class].empty());
-
- DynInstPtr issuing_inst = readyInsts[op_class].top();
-
- assert(issuing_inst->seqNum == (*order_it).oldestInst);
-
- if (issuing_inst->isSquashed()) {
- readyInsts[op_class].pop();
-
- if (!readyInsts[op_class].empty()) {
- moveToYoungerInst(order_it);
- } else {
- readyIt[op_class] = listOrder.end();
- queueOnList[op_class] = false;
- }
-
- listOrder.erase(order_it++);
-
- ++iqSquashedInstsIssued;
-
- continue;
- }
-
- int idx = -2;
- int op_latency = 1;
- int tid = issuing_inst->threadNumber;
-
- if (op_class != No_OpClass) {
- idx = fuPool->getUnit(op_class);
-
- if (idx > -1) {
- op_latency = fuPool->getOpLatency(op_class);
- }
- }
-
- // If we have an instruction that doesn't require a FU, or a
- // valid FU, then schedule for execution.
- if (idx == -2 || idx != -1) {
- if (op_latency == 1) {
- i2e_info->size++;
- instsToExecute.push_back(issuing_inst);
-
- // Add the FU onto the list of FU's to be freed next
- // cycle if we used one.
- if (idx >= 0)
- fuPool->freeUnitNextCycle(idx);
- } else {
- int issue_latency = fuPool->getIssueLatency(op_class);
- // Generate completion event for the FU
- FUCompletion *execution = new FUCompletion(issuing_inst,
- idx, this);
-
- execution->schedule(curTick + cpu->cycles(issue_latency - 1));
-
- // @todo: Enforce that issue_latency == 1 or op_latency
- if (issue_latency > 1) {
- // If FU isn't pipelined, then it must be freed
- // upon the execution completing.
- execution->setFreeFU();
- } else {
- // Add the FU onto the list of FU's to be freed next cycle.
- fuPool->freeUnitNextCycle(idx);
- }
- }
-
- DPRINTF(IQ, "Thread %i: Issuing instruction PC %#x "
- "[sn:%lli]\n",
- tid, issuing_inst->readPC(),
- issuing_inst->seqNum);
-
- readyInsts[op_class].pop();
-
- if (!readyInsts[op_class].empty()) {
- moveToYoungerInst(order_it);
- } else {
- readyIt[op_class] = listOrder.end();
- queueOnList[op_class] = false;
- }
-
- issuing_inst->setIssued();
- ++total_issued;
-
- if (!issuing_inst->isMemRef()) {
- // Memory instructions can not be freed from the IQ until they
- // complete.
- ++freeEntries;
- count[tid]--;
- issuing_inst->removeInIQ();
- } else {
- memDepUnit[tid].issue(issuing_inst);
- }
-
- listOrder.erase(order_it++);
- statIssuedInstType[tid][op_class]++;
- } else {
- statFuBusy[op_class]++;
- fuBusy[tid]++;
- ++order_it;
- }
- }
-
- numIssuedDist.sample(total_issued);
- iqInstsIssued+= total_issued;
-
- // If we issued any instructions, tell the CPU we had activity.
- if (total_issued) {
- cpu->activityThisCycle();
- } else {
- DPRINTF(IQ, "Not able to schedule any instructions.\n");
- }
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst)
-{
- DPRINTF(IQ, "Marking nonspeculative instruction [sn:%lli] as ready "
- "to execute.\n", inst);
-
- NonSpecMapIt inst_it = nonSpecInsts.find(inst);
-
- assert(inst_it != nonSpecInsts.end());
-
- unsigned tid = (*inst_it).second->threadNumber;
-
- (*inst_it).second->setCanIssue();
-
- if (!(*inst_it).second->isMemRef()) {
- addIfReady((*inst_it).second);
- } else {
- memDepUnit[tid].nonSpecInstReady((*inst_it).second);
- }
-
- (*inst_it).second = NULL;
-
- nonSpecInsts.erase(inst_it);
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::commit(const InstSeqNum &inst, unsigned tid)
-{
- DPRINTF(IQ, "[tid:%i]: Committing instructions older than [sn:%i]\n",
- tid,inst);
-
- ListIt iq_it = instList[tid].begin();
-
- while (iq_it != instList[tid].end() &&
- (*iq_it)->seqNum <= inst) {
- ++iq_it;
- instList[tid].pop_front();
- }
-
- assert(freeEntries == (numEntries - countInsts()));
-}
-
-template <class Impl>
-int
-InstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst)
-{
- int dependents = 0;
-
- DPRINTF(IQ, "Waking dependents of completed instruction.\n");
-
- assert(!completed_inst->isSquashed());
-
- // Tell the memory dependence unit to wake any dependents on this
- // instruction if it is a memory instruction. Also complete the memory
- // instruction at this point since we know it executed without issues.
- // @todo: Might want to rename "completeMemInst" to something that
- // indicates that it won't need to be replayed, and call this
- // earlier. Might not be a big deal.
- if (completed_inst->isMemRef()) {
- memDepUnit[completed_inst->threadNumber].wakeDependents(completed_inst);
- completeMemInst(completed_inst);
- } else if (completed_inst->isMemBarrier() ||
- completed_inst->isWriteBarrier()) {
- memDepUnit[completed_inst->threadNumber].completeBarrier(completed_inst);
- }
-
- for (int dest_reg_idx = 0;
- dest_reg_idx < completed_inst->numDestRegs();
- dest_reg_idx++)
- {
- PhysRegIndex dest_reg =
- completed_inst->renamedDestRegIdx(dest_reg_idx);
-
- // Special case of uniq or control registers. They are not
- // handled by the IQ and thus have no dependency graph entry.
- // @todo Figure out a cleaner way to handle this.
- if (dest_reg >= numPhysRegs) {
- continue;
- }
-
- DPRINTF(IQ, "Waking any dependents on register %i.\n",
- (int) dest_reg);
-
- //Go through the dependency chain, marking the registers as
- //ready within the waiting instructions.
- DynInstPtr dep_inst = dependGraph.pop(dest_reg);
-
- while (dep_inst) {
- DPRINTF(IQ, "Waking up a dependent instruction, PC%#x.\n",
- dep_inst->readPC());
-
- // Might want to give more information to the instruction
- // so that it knows which of its source registers is
- // ready. However that would mean that the dependency
- // graph entries would need to hold the src_reg_idx.
- dep_inst->markSrcRegReady();
-
- addIfReady(dep_inst);
-
- dep_inst = dependGraph.pop(dest_reg);
-
- ++dependents;
- }
-
- // Reset the head node now that all of its dependents have
- // been woken up.
- assert(dependGraph.empty(dest_reg));
- dependGraph.clearInst(dest_reg);
-
- // Mark the scoreboard as having that register ready.
- regScoreboard[dest_reg] = true;
- }
- return dependents;
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::addReadyMemInst(DynInstPtr &ready_inst)
-{
- OpClass op_class = ready_inst->opClass();
-
- readyInsts[op_class].push(ready_inst);
-
- // Will need to reorder the list if either a queue is not on the list,
- // or it has an older instruction than last time.
- if (!queueOnList[op_class]) {
- addToOrderList(op_class);
- } else if (readyInsts[op_class].top()->seqNum <
- (*readyIt[op_class]).oldestInst) {
- listOrder.erase(readyIt[op_class]);
- addToOrderList(op_class);
- }
-
- DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
- "the ready list, PC %#x opclass:%i [sn:%lli].\n",
- ready_inst->readPC(), op_class, ready_inst->seqNum);
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::rescheduleMemInst(DynInstPtr &resched_inst)
-{
- memDepUnit[resched_inst->threadNumber].reschedule(resched_inst);
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::replayMemInst(DynInstPtr &replay_inst)
-{
- memDepUnit[replay_inst->threadNumber].replay(replay_inst);
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::completeMemInst(DynInstPtr &completed_inst)
-{
- int tid = completed_inst->threadNumber;
-
- DPRINTF(IQ, "Completing mem instruction PC:%#x [sn:%lli]\n",
- completed_inst->readPC(), completed_inst->seqNum);
-
- ++freeEntries;
-
- completed_inst->memOpDone = true;
-
- memDepUnit[tid].completed(completed_inst);
-
- count[tid]--;
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::violation(DynInstPtr &store,
- DynInstPtr &faulting_load)
-{
- memDepUnit[store->threadNumber].violation(store, faulting_load);
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::squash(unsigned tid)
-{
- DPRINTF(IQ, "[tid:%i]: Starting to squash instructions in "
- "the IQ.\n", tid);
-
- // Read instruction sequence number of last instruction out of the
- // time buffer.
- squashedSeqNum[tid] = fromCommit->commitInfo[tid].doneSeqNum;
-
- // Call doSquash if there are insts in the IQ
- if (count[tid] > 0) {
- doSquash(tid);
- }
-
- // Also tell the memory dependence unit to squash.
- memDepUnit[tid].squash(squashedSeqNum[tid], tid);
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::doSquash(unsigned tid)
-{
- // Start at the tail.
- ListIt squash_it = instList[tid].end();
- --squash_it;
-
- DPRINTF(IQ, "[tid:%i]: Squashing until sequence number %i!\n",
- tid, squashedSeqNum[tid]);
-
- // Squash any instructions younger than the squashed sequence number
- // given.
- while (squash_it != instList[tid].end() &&
- (*squash_it)->seqNum > squashedSeqNum[tid]) {
-
- DynInstPtr squashed_inst = (*squash_it);
-
- // Only handle the instruction if it actually is in the IQ and
- // hasn't already been squashed in the IQ.
- if (squashed_inst->threadNumber != tid ||
- squashed_inst->isSquashedInIQ()) {
- --squash_it;
- continue;
- }
-
- if (!squashed_inst->isIssued() ||
- (squashed_inst->isMemRef() &&
- !squashed_inst->memOpDone)) {
-
- // Remove the instruction from the dependency list.
- if (!squashed_inst->isNonSpeculative() &&
- !squashed_inst->isStoreConditional() &&
- !squashed_inst->isMemBarrier() &&
- !squashed_inst->isWriteBarrier()) {
-
- for (int src_reg_idx = 0;
- src_reg_idx < squashed_inst->numSrcRegs();
- src_reg_idx++)
- {
- PhysRegIndex src_reg =
- squashed_inst->renamedSrcRegIdx(src_reg_idx);
-
- // Only remove it from the dependency graph if it
- // was placed there in the first place.
-
- // Instead of doing a linked list traversal, we
- // can just remove these squashed instructions
- // either at issue time, or when the register is
- // overwritten. The only downside to this is it
- // leaves more room for error.
-
- if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) &&
- src_reg < numPhysRegs) {
- dependGraph.remove(src_reg, squashed_inst);
- }
-
-
- ++iqSquashedOperandsExamined;
- }
- } else {
- NonSpecMapIt ns_inst_it =
- nonSpecInsts.find(squashed_inst->seqNum);
- assert(ns_inst_it != nonSpecInsts.end());
-
- (*ns_inst_it).second = NULL;
-
- nonSpecInsts.erase(ns_inst_it);
-
- ++iqSquashedNonSpecRemoved;
- }
-
- // Might want to also clear out the head of the dependency graph.
-
- // Mark it as squashed within the IQ.
- squashed_inst->setSquashedInIQ();
-
- // @todo: Remove this hack where several statuses are set so the
- // inst will flow through the rest of the pipeline.
- squashed_inst->setIssued();
- squashed_inst->setCanCommit();
- squashed_inst->removeInIQ();
-
- //Update Thread IQ Count
- count[squashed_inst->threadNumber]--;
-
- ++freeEntries;
-
- DPRINTF(IQ, "[tid:%i]: Instruction [sn:%lli] PC %#x "
- "squashed.\n",
- tid, squashed_inst->seqNum, squashed_inst->readPC());
- }
-
- instList[tid].erase(squash_it--);
- ++iqSquashedInstsExamined;
- }
-}
-
-template <class Impl>
-bool
-InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst)
-{
- // Loop through the instruction's source registers, adding
- // them to the dependency list if they are not ready.
- int8_t total_src_regs = new_inst->numSrcRegs();
- bool return_val = false;
-
- for (int src_reg_idx = 0;
- src_reg_idx < total_src_regs;
- src_reg_idx++)
- {
- // Only add it to the dependency graph if it's not ready.
- if (!new_inst->isReadySrcRegIdx(src_reg_idx)) {
- PhysRegIndex src_reg = new_inst->renamedSrcRegIdx(src_reg_idx);
-
- // Check the IQ's scoreboard to make sure the register
- // hasn't become ready while the instruction was in flight
- // between stages. Only if it really isn't ready should
- // it be added to the dependency graph.
- if (src_reg >= numPhysRegs) {
- continue;
- } else if (regScoreboard[src_reg] == false) {
- DPRINTF(IQ, "Instruction PC %#x has src reg %i that "
- "is being added to the dependency chain.\n",
- new_inst->readPC(), src_reg);
-
- dependGraph.insert(src_reg, new_inst);
-
- // Change the return value to indicate that something
- // was added to the dependency graph.
- return_val = true;
- } else {
- DPRINTF(IQ, "Instruction PC %#x has src reg %i that "
- "became ready before it reached the IQ.\n",
- new_inst->readPC(), src_reg);
- // Mark a register ready within the instruction.
- new_inst->markSrcRegReady(src_reg_idx);
- }
- }
- }
-
- return return_val;
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::addToProducers(DynInstPtr &new_inst)
-{
- // Nothing really needs to be marked when an instruction becomes
- // the producer of a register's value, but for convenience a ptr
- // to the producing instruction will be placed in the head node of
- // the dependency links.
- int8_t total_dest_regs = new_inst->numDestRegs();
-
- for (int dest_reg_idx = 0;
- dest_reg_idx < total_dest_regs;
- dest_reg_idx++)
- {
- PhysRegIndex dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx);
-
- // Instructions that use the misc regs will have a reg number
- // higher than the normal physical registers. In this case these
- // registers are not renamed, and there is no need to track
- // dependencies as these instructions must be executed at commit.
- if (dest_reg >= numPhysRegs) {
- continue;
- }
-
- if (!dependGraph.empty(dest_reg)) {
- dependGraph.dump();
- panic("Dependency graph %i not empty!", dest_reg);
- }
-
- dependGraph.setInst(dest_reg, new_inst);
-
- // Mark the scoreboard to say it's not yet ready.
- regScoreboard[dest_reg] = false;
- }
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::addIfReady(DynInstPtr &inst)
-{
- // If the instruction now has all of its source registers
- // available, then add it to the list of ready instructions.
- if (inst->readyToIssue()) {
-
- //Add the instruction to the proper ready list.
- if (inst->isMemRef()) {
-
- DPRINTF(IQ, "Checking if memory instruction can issue.\n");
-
- // Message to the mem dependence unit that this instruction has
- // its registers ready.
- memDepUnit[inst->threadNumber].regsReady(inst);
-
- return;
- }
-
- OpClass op_class = inst->opClass();
-
- DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
- "the ready list, PC %#x opclass:%i [sn:%lli].\n",
- inst->readPC(), op_class, inst->seqNum);
-
- readyInsts[op_class].push(inst);
-
- // Will need to reorder the list if either a queue is not on the list,
- // or it has an older instruction than last time.
- if (!queueOnList[op_class]) {
- addToOrderList(op_class);
- } else if (readyInsts[op_class].top()->seqNum <
- (*readyIt[op_class]).oldestInst) {
- listOrder.erase(readyIt[op_class]);
- addToOrderList(op_class);
- }
- }
-}
-
-template <class Impl>
-int
-InstructionQueue<Impl>::countInsts()
-{
- //ksewell:This works but definitely could use a cleaner write
- //with a more intuitive way of counting. Right now it's
- //just brute force ....
-
-#if 0
- int total_insts = 0;
-
- for (int i = 0; i < numThreads; ++i) {
- ListIt count_it = instList[i].begin();
-
- while (count_it != instList[i].end()) {
- if (!(*count_it)->isSquashed() && !(*count_it)->isSquashedInIQ()) {
- if (!(*count_it)->isIssued()) {
- ++total_insts;
- } else if ((*count_it)->isMemRef() &&
- !(*count_it)->memOpDone) {
- // Loads that have not been marked as executed still count
- // towards the total instructions.
- ++total_insts;
- }
- }
-
- ++count_it;
- }
- }
-
- return total_insts;
-#else
- return numEntries - freeEntries;
-#endif
-}
-
-template <class Impl>
-void
-InstructionQueue<Impl>::dumpLists()
-{
- for (int i = 0; i < Num_OpClasses; ++i) {
- cprintf("Ready list %i size: %i\n", i, readyInsts[i].size());
-
- cprintf("\n");
- }
-
- cprintf("Non speculative list size: %i\n", nonSpecInsts.size());
-
- NonSpecMapIt non_spec_it = nonSpecInsts.begin();
- NonSpecMapIt non_spec_end_it = nonSpecInsts.end();
-
- cprintf("Non speculative list: ");
-
- while (non_spec_it != non_spec_end_it) {
- cprintf("%#x [sn:%lli]", (*non_spec_it).second->readPC(),
- (*non_spec_it).second->seqNum);
- ++non_spec_it;
- }
-
- cprintf("\n");
-
- ListOrderIt list_order_it = listOrder.begin();
- ListOrderIt list_order_end_it = listOrder.end();
- int i = 1;
-
- cprintf("List order: ");
-
- while (list_order_it != list_order_end_it) {
- cprintf("%i OpClass:%i [sn:%lli] ", i, (*list_order_it).queueType,
- (*list_order_it).oldestInst);
-
- ++list_order_it;
- ++i;
- }
-
- cprintf("\n");
-}
-
-
-template <class Impl>
-void
-InstructionQueue<Impl>::dumpInsts()
-{
- for (int i = 0; i < numThreads; ++i) {
- int num = 0;
- int valid_num = 0;
- ListIt inst_list_it = instList[i].begin();
-
- while (inst_list_it != instList[i].end())
- {
- cprintf("Instruction:%i\n",
- num);
- if (!(*inst_list_it)->isSquashed()) {
- if (!(*inst_list_it)->isIssued()) {
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- } else if ((*inst_list_it)->isMemRef() &&
- !(*inst_list_it)->memOpDone) {
- // Loads that have not been marked as executed
- // still count towards the total instructions.
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- }
- }
-
- cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
- "Issued:%i\nSquashed:%i\n",
- (*inst_list_it)->readPC(),
- (*inst_list_it)->seqNum,
- (*inst_list_it)->threadNumber,
- (*inst_list_it)->isIssued(),
- (*inst_list_it)->isSquashed());
-
- if ((*inst_list_it)->isMemRef()) {
- cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
- }
-
- cprintf("\n");
-
- inst_list_it++;
- ++num;
- }
- }
-
- cprintf("Insts to Execute list:\n");
-
- int num = 0;
- int valid_num = 0;
- ListIt inst_list_it = instsToExecute.begin();
-
- while (inst_list_it != instsToExecute.end())
- {
- cprintf("Instruction:%i\n",
- num);
- if (!(*inst_list_it)->isSquashed()) {
- if (!(*inst_list_it)->isIssued()) {
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- } else if ((*inst_list_it)->isMemRef() &&
- !(*inst_list_it)->memOpDone) {
- // Loads that have not been marked as executed
- // still count towards the total instructions.
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- }
- }
-
- cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
- "Issued:%i\nSquashed:%i\n",
- (*inst_list_it)->readPC(),
- (*inst_list_it)->seqNum,
- (*inst_list_it)->threadNumber,
- (*inst_list_it)->isIssued(),
- (*inst_list_it)->isSquashed());
-
- if ((*inst_list_it)->isMemRef()) {
- cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
- }
-
- cprintf("\n");
-
- inst_list_it++;
- ++num;
- }
-}
diff --git a/cpu/o3/lsq.cc b/cpu/o3/lsq.cc
deleted file mode 100644
index 8991ab8f8..000000000
--- a/cpu/o3/lsq.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/o3/alpha_dyn_inst.hh"
-#include "cpu/o3/alpha_cpu.hh"
-#include "cpu/o3/alpha_impl.hh"
-#include "cpu/o3/lsq_impl.hh"
-
-// Force the instantiation of LDSTQ for all the implementations we care about.
-template class LSQ<AlphaSimpleImpl>;
-
diff --git a/cpu/o3/lsq.hh b/cpu/o3/lsq.hh
deleted file mode 100644
index b321d4590..000000000
--- a/cpu/o3/lsq.hh
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_LSQ_HH__
-#define __CPU_O3_LSQ_HH__
-
-#include <map>
-#include <queue>
-
-#include "config/full_system.hh"
-#include "cpu/inst_seq.hh"
-//#include "cpu/o3/cpu_policy.hh"
-#include "cpu/o3/lsq_unit.hh"
-#include "mem/mem_interface.hh"
-//#include "mem/page_table.hh"
-#include "sim/sim_object.hh"
-
-template <class Impl>
-class LSQ {
- public:
- typedef typename Impl::Params Params;
- typedef typename Impl::FullCPU FullCPU;
- typedef typename Impl::DynInstPtr DynInstPtr;
- typedef typename Impl::CPUPol::IEW IEW;
- typedef typename Impl::CPUPol::LSQUnit LSQUnit;
-
- /** SMT policy. */
- enum LSQPolicy {
- Dynamic,
- Partitioned,
- Threshold
- };
-
- /** Constructs an LSQ with the given parameters. */
- LSQ(Params *params);
-
- /** Returns the name of the LSQ. */
- std::string name() const;
-
- /** Sets the pointer to the list of active threads. */
- void setActiveThreads(std::list<unsigned> *at_ptr);
- /** Sets the CPU pointer. */
- void setCPU(FullCPU *cpu_ptr);
- /** Sets the IEW stage pointer. */
- void setIEW(IEW *iew_ptr);
- /** Sets the page table pointer. */
-// void setPageTable(PageTable *pt_ptr);
- /** Switches out the LSQ. */
- void switchOut();
- /** Takes over execution from another CPU's thread. */
- void takeOverFrom();
-
- /** Number of entries needed for the given amount of threads.*/
- int entryAmount(int num_threads);
- void removeEntries(unsigned tid);
- /** Reset the max entries for each thread. */
- void resetEntries();
- /** Resize the max entries for a thread. */
- void resizeEntries(unsigned size, unsigned tid);
-
- /** Ticks the LSQ. */
- void tick();
- /** Ticks a specific LSQ Unit. */
- void tick(unsigned tid)
- { thread[tid].tick(); }
-
- /** Inserts a load into the LSQ. */
- void insertLoad(DynInstPtr &load_inst);
- /** Inserts a store into the LSQ. */
- void insertStore(DynInstPtr &store_inst);
-
- /** Executes a load. */
- Fault executeLoad(DynInstPtr &inst);
-
- /** Executes a store. */
- Fault executeStore(DynInstPtr &inst);
-
- /**
- * Commits loads up until the given sequence number for a specific thread.
- */
- void commitLoads(InstSeqNum &youngest_inst, unsigned tid)
- { thread[tid].commitLoads(youngest_inst); }
-
- /**
- * Commits stores up until the given sequence number for a specific thread.
- */
- void commitStores(InstSeqNum &youngest_inst, unsigned tid)
- { thread[tid].commitStores(youngest_inst); }
-
- /**
- * Attempts to write back stores until all cache ports are used or the
- * interface becomes blocked.
- */
- void writebackStores();
- /** Same as above, but only for one thread. */
- void writebackStores(unsigned tid);
-
- /**
- * Squash instructions from a thread until the specified sequence number.
- */
- void squash(const InstSeqNum &squashed_num, unsigned tid)
- { thread[tid].squash(squashed_num); }
-
- /** Returns whether or not there was a memory ordering violation. */
- bool violation();
- /**
- * Returns whether or not there was a memory ordering violation for a
- * specific thread.
- */
- bool violation(unsigned tid)
- { return thread[tid].violation(); }
-
- /** Returns if a load is blocked due to the memory system for a specific
- * thread.
- */
- bool loadBlocked(unsigned tid)
- { return thread[tid].loadBlocked(); }
-
- bool isLoadBlockedHandled(unsigned tid)
- { return thread[tid].isLoadBlockedHandled(); }
-
- void setLoadBlockedHandled(unsigned tid)
- { thread[tid].setLoadBlockedHandled(); }
-
- /** Gets the instruction that caused the memory ordering violation. */
- DynInstPtr getMemDepViolator(unsigned tid)
- { return thread[tid].getMemDepViolator(); }
-
- /** Returns the head index of the load queue for a specific thread. */
- int getLoadHead(unsigned tid)
- { return thread[tid].getLoadHead(); }
-
- /** Returns the sequence number of the head of the load queue. */
- InstSeqNum getLoadHeadSeqNum(unsigned tid)
- {
- return thread[tid].getLoadHeadSeqNum();
- }
-
- /** Returns the head index of the store queue. */
- int getStoreHead(unsigned tid)
- { return thread[tid].getStoreHead(); }
-
- /** Returns the sequence number of the head of the store queue. */
- InstSeqNum getStoreHeadSeqNum(unsigned tid)
- {
- return thread[tid].getStoreHeadSeqNum();
- }
-
- /** Returns the number of instructions in all of the queues. */
- int getCount();
- /** Returns the number of instructions in the queues of one thread. */
- int getCount(unsigned tid)
- { return thread[tid].getCount(); }
-
- /** Returns the total number of loads in the load queue. */
- int numLoads();
- /** Returns the total number of loads for a single thread. */
- int numLoads(unsigned tid)
- { return thread[tid].numLoads(); }
-
- /** Returns the total number of stores in the store queue. */
- int numStores();
- /** Returns the total number of stores for a single thread. */
- int numStores(unsigned tid)
- { return thread[tid].numStores(); }
-
- /** Returns the total number of loads that are ready. */
- int numLoadsReady();
- /** Returns the number of loads that are ready for a single thread. */
- int numLoadsReady(unsigned tid)
- { return thread[tid].numLoadsReady(); }
-
- /** Returns the number of free entries. */
- unsigned numFreeEntries();
- /** Returns the number of free entries for a specific thread. */
- unsigned numFreeEntries(unsigned tid);
-
- /** Returns if the LSQ is full (either LQ or SQ is full). */
- bool isFull();
- /**
- * Returns if the LSQ is full for a specific thread (either LQ or SQ is
- * full).
- */
- bool isFull(unsigned tid);
-
- /** Returns if any of the LQs are full. */
- bool lqFull();
- /** Returns if the LQ of a given thread is full. */
- bool lqFull(unsigned tid);
-
- /** Returns if any of the SQs are full. */
- bool sqFull();
- /** Returns if the SQ of a given thread is full. */
- bool sqFull(unsigned tid);
-
- /**
- * Returns if the LSQ is stalled due to a memory operation that must be
- * replayed.
- */
- bool isStalled();
- /**
- * Returns if the LSQ of a specific thread is stalled due to a memory
- * operation that must be replayed.
- */
- bool isStalled(unsigned tid);
-
- /** Returns whether or not there are any stores to write back to memory. */
- bool hasStoresToWB();
-
- /** Returns whether or not a specific thread has any stores to write back
- * to memory.
- */
- bool hasStoresToWB(unsigned tid)
- { return thread[tid].hasStoresToWB(); }
-
- /** Returns the number of stores a specific thread has to write back. */
- int numStoresToWB(unsigned tid)
- { return thread[tid].numStoresToWB(); }
-
- /** Returns if the LSQ will write back to memory this cycle. */
- bool willWB();
- /** Returns if the LSQ of a specific thread will write back to memory this
- * cycle.
- */
- bool willWB(unsigned tid)
- { return thread[tid].willWB(); }
-
- /** Debugging function to print out all instructions. */
- void dumpInsts();
- /** Debugging function to print out instructions from a specific thread. */
- void dumpInsts(unsigned tid)
- { thread[tid].dumpInsts(); }
-
- /** Executes a read operation, using the load specified at the load index. */
- template <class T>
- Fault read(MemReqPtr &req, T &data, int load_idx);
-
- /** Executes a store operation, using the store specified at the store
- * index.
- */
- template <class T>
- Fault write(MemReqPtr &req, T &data, int store_idx);
-
- private:
- /** The LSQ policy for SMT mode. */
- LSQPolicy lsqPolicy;
-
- /** The LSQ units for individual threads. */
- LSQUnit thread[Impl::MaxThreads];
-
- /** The CPU pointer. */
- FullCPU *cpu;
-
- /** The IEW stage pointer. */
- IEW *iewStage;
-
- /** The pointer to the page table. */
-// PageTable *pTable;
-
- /** List of Active Threads in System. */
- std::list<unsigned> *activeThreads;
-
- /** Total Size of LQ Entries. */
- unsigned LQEntries;
- /** Total Size of SQ Entries. */
- unsigned SQEntries;
-
- /** Max LQ Size - Used to Enforce Sharing Policies. */
- unsigned maxLQEntries;
-
- /** Max SQ Size - Used to Enforce Sharing Policies. */
- unsigned maxSQEntries;
-
- /** Number of Threads. */
- unsigned numThreads;
-};
-
-template <class Impl>
-template <class T>
-Fault
-LSQ<Impl>::read(MemReqPtr &req, T &data, int load_idx)
-{
- unsigned tid = req->thread_num;
-
- return thread[tid].read(req, data, load_idx);
-}
-
-template <class Impl>
-template <class T>
-Fault
-LSQ<Impl>::write(MemReqPtr &req, T &data, int store_idx)
-{
- unsigned tid = req->thread_num;
-
- return thread[tid].write(req, data, store_idx);
-}
-
-#endif // __CPU_O3_LSQ_HH__
diff --git a/cpu/o3/lsq_impl.hh b/cpu/o3/lsq_impl.hh
deleted file mode 100644
index a6ad27522..000000000
--- a/cpu/o3/lsq_impl.hh
+++ /dev/null
@@ -1,538 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <algorithm>
-#include <string>
-
-#include "cpu/o3/lsq.hh"
-
-using namespace std;
-
-template <class Impl>
-LSQ<Impl>::LSQ(Params *params)
- : LQEntries(params->LQEntries), SQEntries(params->SQEntries),
- numThreads(params->numberOfThreads)
-{
- DPRINTF(LSQ, "Creating LSQ object.\n");
-
- //**********************************************/
- //************ Handle SMT Parameters ***********/
- //**********************************************/
- string policy = params->smtLSQPolicy;
-
- //Convert string to lowercase
- std::transform(policy.begin(), policy.end(), policy.begin(),
- (int(*)(int)) tolower);
-
- //Figure out fetch policy
- if (policy == "dynamic") {
- lsqPolicy = Dynamic;
-
- maxLQEntries = LQEntries;
- maxSQEntries = SQEntries;
-
- DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n");
-
- } else if (policy == "partitioned") {
- lsqPolicy = Partitioned;
-
- //@todo:make work if part_amt doesnt divide evenly.
- maxLQEntries = LQEntries / numThreads;
- maxSQEntries = SQEntries / numThreads;
-
- DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: "
- "%i entries per LQ | %i entries per SQ",
- maxLQEntries,maxSQEntries);
-
- } else if (policy == "threshold") {
- lsqPolicy = Threshold;
-
- assert(params->smtLSQThreshold > LQEntries);
- assert(params->smtLSQThreshold > SQEntries);
-
- //Divide up by threshold amount
- //@todo: Should threads check the max and the total
- //amount of the LSQ
- maxLQEntries = params->smtLSQThreshold;
- maxSQEntries = params->smtLSQThreshold;
-
- DPRINTF(LSQ, "LSQ sharing policy set to Threshold: "
- "%i entries per LQ | %i entries per SQ",
- maxLQEntries,maxSQEntries);
-
- } else {
- assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic,"
- "Partitioned, Threshold}");
- }
-
- //Initialize LSQs
- for (int tid=0; tid < numThreads; tid++) {
- thread[tid].init(params, maxLQEntries, maxSQEntries, tid);
- }
-}
-
-
-template<class Impl>
-std::string
-LSQ<Impl>::name() const
-{
- return iewStage->name() + ".lsq";
-}
-
-template<class Impl>
-void
-LSQ<Impl>::setActiveThreads(list<unsigned> *at_ptr)
-{
- activeThreads = at_ptr;
- assert(activeThreads != 0);
-}
-
-template<class Impl>
-void
-LSQ<Impl>::setCPU(FullCPU *cpu_ptr)
-{
- cpu = cpu_ptr;
-
- for (int tid=0; tid < numThreads; tid++) {
- thread[tid].setCPU(cpu_ptr);
- }
-}
-
-template<class Impl>
-void
-LSQ<Impl>::setIEW(IEW *iew_ptr)
-{
- iewStage = iew_ptr;
-
- for (int tid=0; tid < numThreads; tid++) {
- thread[tid].setIEW(iew_ptr);
- }
-}
-
-#if 0
-template<class Impl>
-void
-LSQ<Impl>::setPageTable(PageTable *pt_ptr)
-{
- for (int tid=0; tid < numThreads; tid++) {
- thread[tid].setPageTable(pt_ptr);
- }
-}
-#endif
-
-template <class Impl>
-void
-LSQ<Impl>::switchOut()
-{
- for (int tid = 0; tid < numThreads; tid++) {
- thread[tid].switchOut();
- }
-}
-
-template <class Impl>
-void
-LSQ<Impl>::takeOverFrom()
-{
- for (int tid = 0; tid < numThreads; tid++) {
- thread[tid].takeOverFrom();
- }
-}
-
-template <class Impl>
-int
-LSQ<Impl>::entryAmount(int num_threads)
-{
- if (lsqPolicy == Partitioned) {
- return LQEntries / num_threads;
- } else {
- return 0;
- }
-}
-
-template <class Impl>
-void
-LSQ<Impl>::resetEntries()
-{
- if (lsqPolicy != Dynamic || numThreads > 1) {
- int active_threads = (*activeThreads).size();
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
- list<unsigned>::iterator list_end = (*activeThreads).end();
-
- int maxEntries;
-
- if (lsqPolicy == Partitioned) {
- maxEntries = LQEntries / active_threads;
- } else if (lsqPolicy == Threshold && active_threads == 1) {
- maxEntries = LQEntries;
- } else {
- maxEntries = LQEntries;
- }
-
- while (threads != list_end) {
- resizeEntries(maxEntries,*threads++);
- }
- }
-}
-
-template<class Impl>
-void
-LSQ<Impl>::removeEntries(unsigned tid)
-{
- thread[tid].clearLQ();
- thread[tid].clearSQ();
-}
-
-template<class Impl>
-void
-LSQ<Impl>::resizeEntries(unsigned size,unsigned tid)
-{
- thread[tid].resizeLQ(size);
- thread[tid].resizeSQ(size);
-}
-
-template<class Impl>
-void
-LSQ<Impl>::tick()
-{
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
-
- while (active_threads != (*activeThreads).end()) {
- unsigned tid = *active_threads++;
-
- thread[tid].tick();
- }
-}
-
-template<class Impl>
-void
-LSQ<Impl>::insertLoad(DynInstPtr &load_inst)
-{
- unsigned tid = load_inst->threadNumber;
-
- thread[tid].insertLoad(load_inst);
-}
-
-template<class Impl>
-void
-LSQ<Impl>::insertStore(DynInstPtr &store_inst)
-{
- unsigned tid = store_inst->threadNumber;
-
- thread[tid].insertStore(store_inst);
-}
-
-template<class Impl>
-Fault
-LSQ<Impl>::executeLoad(DynInstPtr &inst)
-{
- unsigned tid = inst->threadNumber;
-
- return thread[tid].executeLoad(inst);
-}
-
-template<class Impl>
-Fault
-LSQ<Impl>::executeStore(DynInstPtr &inst)
-{
- unsigned tid = inst->threadNumber;
-
- return thread[tid].executeStore(inst);
-}
-
-template<class Impl>
-void
-LSQ<Impl>::writebackStores()
-{
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
-
- while (active_threads != (*activeThreads).end()) {
- unsigned tid = *active_threads++;
-
- if (numStoresToWB(tid) > 0) {
- DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores "
- "available for Writeback.\n", tid, numStoresToWB(tid));
- }
-
- thread[tid].writebackStores();
- }
-}
-
-template<class Impl>
-bool
-LSQ<Impl>::violation()
-{
- /* Answers: Does Anybody Have a Violation?*/
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
-
- while (active_threads != (*activeThreads).end()) {
- unsigned tid = *active_threads++;
- if (thread[tid].violation())
- return true;
- }
-
- return false;
-}
-
-template<class Impl>
-int
-LSQ<Impl>::getCount()
-{
- unsigned total = 0;
-
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
-
- while (active_threads != (*activeThreads).end()) {
- unsigned tid = *active_threads++;
- total += getCount(tid);
- }
-
- return total;
-}
-
-template<class Impl>
-int
-LSQ<Impl>::numLoads()
-{
- unsigned total = 0;
-
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
-
- while (active_threads != (*activeThreads).end()) {
- unsigned tid = *active_threads++;
- total += numLoads(tid);
- }
-
- return total;
-}
-
-template<class Impl>
-int
-LSQ<Impl>::numStores()
-{
- unsigned total = 0;
-
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
-
- while (active_threads != (*activeThreads).end()) {
- unsigned tid = *active_threads++;
- total += thread[tid].numStores();
- }
-
- return total;
-}
-
-template<class Impl>
-int
-LSQ<Impl>::numLoadsReady()
-{
- unsigned total = 0;
-
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
-
- while (active_threads != (*activeThreads).end()) {
- unsigned tid = *active_threads++;
- total += thread[tid].numLoadsReady();
- }
-
- return total;
-}
-
-template<class Impl>
-unsigned
-LSQ<Impl>::numFreeEntries()
-{
- unsigned total = 0;
-
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
-
- while (active_threads != (*activeThreads).end()) {
- unsigned tid = *active_threads++;
- total += thread[tid].numFreeEntries();
- }
-
- return total;
-}
-
-template<class Impl>
-unsigned
-LSQ<Impl>::numFreeEntries(unsigned tid)
-{
- //if( lsqPolicy == Dynamic )
- //return numFreeEntries();
- //else
- return thread[tid].numFreeEntries();
-}
-
-template<class Impl>
-bool
-LSQ<Impl>::isFull()
-{
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
-
- while (active_threads != (*activeThreads).end()) {
- unsigned tid = *active_threads++;
- if (! (thread[tid].lqFull() || thread[tid].sqFull()) )
- return false;
- }
-
- return true;
-}
-
-template<class Impl>
-bool
-LSQ<Impl>::isFull(unsigned tid)
-{
- //@todo: Change to Calculate All Entries for
- //Dynamic Policy
- if( lsqPolicy == Dynamic )
- return isFull();
- else
- return thread[tid].lqFull() || thread[tid].sqFull();
-}
-
-template<class Impl>
-bool
-LSQ<Impl>::lqFull()
-{
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
-
- while (active_threads != (*activeThreads).end()) {
- unsigned tid = *active_threads++;
- if (!thread[tid].lqFull())
- return false;
- }
-
- return true;
-}
-
-template<class Impl>
-bool
-LSQ<Impl>::lqFull(unsigned tid)
-{
- //@todo: Change to Calculate All Entries for
- //Dynamic Policy
- if( lsqPolicy == Dynamic )
- return lqFull();
- else
- return thread[tid].lqFull();
-}
-
-template<class Impl>
-bool
-LSQ<Impl>::sqFull()
-{
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
-
- while (active_threads != (*activeThreads).end()) {
- unsigned tid = *active_threads++;
- if (!sqFull(tid))
- return false;
- }
-
- return true;
-}
-
-template<class Impl>
-bool
-LSQ<Impl>::sqFull(unsigned tid)
-{
- //@todo: Change to Calculate All Entries for
- //Dynamic Policy
- if( lsqPolicy == Dynamic )
- return sqFull();
- else
- return thread[tid].sqFull();
-}
-
-template<class Impl>
-bool
-LSQ<Impl>::isStalled()
-{
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
-
- while (active_threads != (*activeThreads).end()) {
- unsigned tid = *active_threads++;
- if (!thread[tid].isStalled())
- return false;
- }
-
- return true;
-}
-
-template<class Impl>
-bool
-LSQ<Impl>::isStalled(unsigned tid)
-{
- if( lsqPolicy == Dynamic )
- return isStalled();
- else
- return thread[tid].isStalled();
-}
-
-template<class Impl>
-bool
-LSQ<Impl>::hasStoresToWB()
-{
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
-
- while (active_threads != (*activeThreads).end()) {
- unsigned tid = *active_threads++;
- if (!hasStoresToWB(tid))
- return false;
- }
-
- return true;
-}
-
-template<class Impl>
-bool
-LSQ<Impl>::willWB()
-{
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
-
- while (active_threads != (*activeThreads).end()) {
- unsigned tid = *active_threads++;
- if (!willWB(tid))
- return false;
- }
-
- return true;
-}
-
-template<class Impl>
-void
-LSQ<Impl>::dumpInsts()
-{
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
-
- while (active_threads != (*activeThreads).end()) {
- unsigned tid = *active_threads++;
- thread[tid].dumpInsts();
- }
-}
diff --git a/cpu/o3/lsq_unit.cc b/cpu/o3/lsq_unit.cc
deleted file mode 100644
index dd29007bc..000000000
--- a/cpu/o3/lsq_unit.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/o3/alpha_dyn_inst.hh"
-#include "cpu/o3/alpha_cpu.hh"
-#include "cpu/o3/alpha_impl.hh"
-#include "cpu/o3/lsq_unit_impl.hh"
-
-// Force the instantiation of LDSTQ for all the implementations we care about.
-template class LSQUnit<AlphaSimpleImpl>;
-
diff --git a/cpu/o3/lsq_unit.hh b/cpu/o3/lsq_unit.hh
deleted file mode 100644
index a6afff743..000000000
--- a/cpu/o3/lsq_unit.hh
+++ /dev/null
@@ -1,641 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_LSQ_UNIT_HH__
-#define __CPU_O3_LSQ_UNIT_HH__
-
-#include <algorithm>
-#include <map>
-#include <queue>
-
-#include "arch/faults.hh"
-#include "config/full_system.hh"
-#include "base/hashmap.hh"
-#include "cpu/inst_seq.hh"
-#include "mem/mem_interface.hh"
-//#include "mem/page_table.hh"
-//#include "sim/debug.hh"
-//#include "sim/sim_object.hh"
-
-/**
- * Class that implements the actual LQ and SQ for each specific
- * thread. Both are circular queues; load entries are freed upon
- * committing, while store entries are freed once they writeback. The
- * LSQUnit tracks if there are memory ordering violations, and also
- * detects partial load to store forwarding cases (a store only has
- * part of a load's data) that requires the load to wait until the
- * store writes back. In the former case it holds onto the instruction
- * until the dependence unit looks at it, and in the latter it stalls
- * the LSQ until the store writes back. At that point the load is
- * replayed.
- */
-template <class Impl>
-class LSQUnit {
- protected:
- typedef TheISA::IntReg IntReg;
- public:
- typedef typename Impl::Params Params;
- typedef typename Impl::FullCPU FullCPU;
- typedef typename Impl::DynInstPtr DynInstPtr;
- typedef typename Impl::CPUPol::IEW IEW;
- typedef typename Impl::CPUPol::IssueStruct IssueStruct;
-
- private:
- class StoreCompletionEvent : public Event {
- public:
- /** Constructs a store completion event. */
- StoreCompletionEvent(int store_idx, Event *wb_event, LSQUnit *lsq_ptr);
-
- /** Processes the store completion event. */
- void process();
-
- /** Returns the description of this event. */
- const char *description();
-
- /** The writeback event for the store. Needed for store
- * conditionals.
- */
- Event *wbEvent;
-
- private:
- /** The store index of the store being written back. */
- int storeIdx;
- private:
- /** The pointer to the LSQ unit that issued the store. */
- LSQUnit<Impl> *lsqPtr;
- };
-
- public:
- /** Constructs an LSQ unit. init() must be called prior to use. */
- LSQUnit();
-
- /** Initializes the LSQ unit with the specified number of entries. */
- void init(Params *params, unsigned maxLQEntries,
- unsigned maxSQEntries, unsigned id);
-
- /** Returns the name of the LSQ unit. */
- std::string name() const;
-
- /** Sets the CPU pointer. */
- void setCPU(FullCPU *cpu_ptr)
- { cpu = cpu_ptr; }
-
- /** Sets the IEW stage pointer. */
- void setIEW(IEW *iew_ptr)
- { iewStage = iew_ptr; }
-
- /** Sets the page table pointer. */
-// void setPageTable(PageTable *pt_ptr);
-
- /** Switches out LSQ unit. */
- void switchOut();
-
- /** Takes over from another CPU's thread. */
- void takeOverFrom();
-
- /** Returns if the LSQ is switched out. */
- bool isSwitchedOut() { return switchedOut; }
-
- /** Ticks the LSQ unit, which in this case only resets the number of
- * used cache ports.
- * @todo: Move the number of used ports up to the LSQ level so it can
- * be shared by all LSQ units.
- */
- void tick() { usedPorts = 0; }
-
- /** Inserts an instruction. */
- void insert(DynInstPtr &inst);
- /** Inserts a load instruction. */
- void insertLoad(DynInstPtr &load_inst);
- /** Inserts a store instruction. */
- void insertStore(DynInstPtr &store_inst);
-
- /** Executes a load instruction. */
- Fault executeLoad(DynInstPtr &inst);
-
- Fault executeLoad(int lq_idx) { panic("Not implemented"); return NoFault; }
- /** Executes a store instruction. */
- Fault executeStore(DynInstPtr &inst);
-
- /** Commits the head load. */
- void commitLoad();
- /** Commits loads older than a specific sequence number. */
- void commitLoads(InstSeqNum &youngest_inst);
-
- /** Commits stores older than a specific sequence number. */
- void commitStores(InstSeqNum &youngest_inst);
-
- /** Writes back stores. */
- void writebackStores();
-
- // @todo: Include stats in the LSQ unit.
- //void regStats();
-
- /** Clears all the entries in the LQ. */
- void clearLQ();
-
- /** Clears all the entries in the SQ. */
- void clearSQ();
-
- /** Resizes the LQ to a given size. */
- void resizeLQ(unsigned size);
-
- /** Resizes the SQ to a given size. */
- void resizeSQ(unsigned size);
-
- /** Squashes all instructions younger than a specific sequence number. */
- void squash(const InstSeqNum &squashed_num);
-
- /** Returns if there is a memory ordering violation. Value is reset upon
- * call to getMemDepViolator().
- */
- bool violation() { return memDepViolator; }
-
- /** Returns the memory ordering violator. */
- DynInstPtr getMemDepViolator();
-
- /** Returns if a load became blocked due to the memory system. */
- bool loadBlocked()
- { return isLoadBlocked; }
-
- /** Clears the signal that a load became blocked. */
- void clearLoadBlocked()
- { isLoadBlocked = false; }
-
- /** Returns if the blocked load was handled. */
- bool isLoadBlockedHandled()
- { return loadBlockedHandled; }
-
- /** Records the blocked load as being handled. */
- void setLoadBlockedHandled()
- { loadBlockedHandled = true; }
-
- /** Returns the number of free entries (min of free LQ and SQ entries). */
- unsigned numFreeEntries();
-
- /** Returns the number of loads ready to execute. */
- int numLoadsReady();
-
- /** Returns the number of loads in the LQ. */
- int numLoads() { return loads; }
-
- /** Returns the number of stores in the SQ. */
- int numStores() { return stores; }
-
- /** Returns if either the LQ or SQ is full. */
- bool isFull() { return lqFull() || sqFull(); }
-
- /** Returns if the LQ is full. */
- bool lqFull() { return loads >= (LQEntries - 1); }
-
- /** Returns if the SQ is full. */
- bool sqFull() { return stores >= (SQEntries - 1); }
-
- /** Returns the number of instructions in the LSQ. */
- unsigned getCount() { return loads + stores; }
-
- /** Returns if there are any stores to writeback. */
- bool hasStoresToWB() { return storesToWB; }
-
- /** Returns the number of stores to writeback. */
- int numStoresToWB() { return storesToWB; }
-
- /** Returns if the LSQ unit will writeback on this cycle. */
- bool willWB() { return storeQueue[storeWBIdx].canWB &&
- !storeQueue[storeWBIdx].completed &&
- !dcacheInterface->isBlocked(); }
-
- private:
- /** Completes the store at the specified index. */
- void completeStore(int store_idx);
-
- /** Increments the given store index (circular queue). */
- inline void incrStIdx(int &store_idx);
- /** Decrements the given store index (circular queue). */
- inline void decrStIdx(int &store_idx);
- /** Increments the given load index (circular queue). */
- inline void incrLdIdx(int &load_idx);
- /** Decrements the given load index (circular queue). */
- inline void decrLdIdx(int &load_idx);
-
- public:
- /** Debugging function to dump instructions in the LSQ. */
- void dumpInsts();
-
- private:
- /** Pointer to the CPU. */
- FullCPU *cpu;
-
- /** Pointer to the IEW stage. */
- IEW *iewStage;
-
- /** Pointer to the D-cache. */
- MemInterface *dcacheInterface;
-
- /** Pointer to the page table. */
-// PageTable *pTable;
-
- public:
- struct SQEntry {
- /** Constructs an empty store queue entry. */
- SQEntry()
- : inst(NULL), req(NULL), size(0), data(0),
- canWB(0), committed(0), completed(0)
- { }
-
- /** Constructs a store queue entry for a given instruction. */
- SQEntry(DynInstPtr &_inst)
- : inst(_inst), req(NULL), size(0), data(0),
- canWB(0), committed(0), completed(0)
- { }
-
- /** The store instruction. */
- DynInstPtr inst;
- /** The memory request for the store. */
- MemReqPtr req;
- /** The size of the store. */
- int size;
- /** The store data. */
- IntReg data;
- /** Whether or not the store can writeback. */
- bool canWB;
- /** Whether or not the store is committed. */
- bool committed;
- /** Whether or not the store is completed. */
- bool completed;
- };
-
- private:
- /** The LSQUnit thread id. */
- unsigned lsqID;
-
- /** The store queue. */
- std::vector<SQEntry> storeQueue;
-
- /** The load queue. */
- std::vector<DynInstPtr> loadQueue;
-
- /** The number of LQ entries, plus a sentinel entry (circular queue).
- * @todo: Consider having var that records the true number of LQ entries.
- */
- unsigned LQEntries;
- /** The number of SQ entries, plus a sentinel entry (circular queue).
- * @todo: Consider having var that records the true number of SQ entries.
- */
- unsigned SQEntries;
-
- /** The number of load instructions in the LQ. */
- int loads;
- /** The number of store instructions in the SQ. */
- int stores;
- /** The number of store instructions in the SQ waiting to writeback. */
- int storesToWB;
-
- /** The index of the head instruction in the LQ. */
- int loadHead;
- /** The index of the tail instruction in the LQ. */
- int loadTail;
-
- /** The index of the head instruction in the SQ. */
- int storeHead;
- /** The index of the first instruction that may be ready to be
- * written back, and has not yet been written back.
- */
- int storeWBIdx;
- /** The index of the tail instruction in the SQ. */
- int storeTail;
-
- /// @todo Consider moving to a more advanced model with write vs read ports
- /** The number of cache ports available each cycle. */
- int cachePorts;
-
- /** The number of used cache ports in this cycle. */
- int usedPorts;
-
- /** Is the LSQ switched out. */
- bool switchedOut;
-
- //list<InstSeqNum> mshrSeqNums;
-
- /** Wire to read information from the issue stage time queue. */
- typename TimeBuffer<IssueStruct>::wire fromIssue;
-
- /** Whether or not the LSQ is stalled. */
- bool stalled;
- /** The store that causes the stall due to partial store to load
- * forwarding.
- */
- InstSeqNum stallingStoreIsn;
- /** The index of the above store. */
- int stallingLoadIdx;
-
- /** Whether or not a load is blocked due to the memory system. */
- bool isLoadBlocked;
-
- /** Has the blocked load been handled. */
- bool loadBlockedHandled;
-
- /** The sequence number of the blocked load. */
- InstSeqNum blockedLoadSeqNum;
-
- /** The oldest load that caused a memory ordering violation. */
- DynInstPtr memDepViolator;
-
- // Will also need how many read/write ports the Dcache has. Or keep track
- // of that in stage that is one level up, and only call executeLoad/Store
- // the appropriate number of times.
-/*
- // total number of loads forwaded from LSQ stores
- Stats::Vector<> lsq_forw_loads;
-
- // total number of loads ignored due to invalid addresses
- Stats::Vector<> inv_addr_loads;
-
- // total number of software prefetches ignored due to invalid addresses
- Stats::Vector<> inv_addr_swpfs;
-
- // total non-speculative bogus addresses seen (debug var)
- Counter sim_invalid_addrs;
- Stats::Vector<> fu_busy; //cumulative fu busy
-
- // ready loads blocked due to memory disambiguation
- Stats::Vector<> lsq_blocked_loads;
-
- Stats::Scalar<> lsqInversion;
-*/
- public:
- /** Executes the load at the given index. */
- template <class T>
- Fault read(MemReqPtr &req, T &data, int load_idx);
-
- /** Executes the store at the given index. */
- template <class T>
- Fault write(MemReqPtr &req, T &data, int store_idx);
-
- /** Returns the index of the head load instruction. */
- int getLoadHead() { return loadHead; }
- /** Returns the sequence number of the head load instruction. */
- InstSeqNum getLoadHeadSeqNum()
- {
- if (loadQueue[loadHead]) {
- return loadQueue[loadHead]->seqNum;
- } else {
- return 0;
- }
-
- }
-
- /** Returns the index of the head store instruction. */
- int getStoreHead() { return storeHead; }
- /** Returns the sequence number of the head store instruction. */
- InstSeqNum getStoreHeadSeqNum()
- {
- if (storeQueue[storeHead].inst) {
- return storeQueue[storeHead].inst->seqNum;
- } else {
- return 0;
- }
-
- }
-
- /** Returns whether or not the LSQ unit is stalled. */
- bool isStalled() { return stalled; }
-};
-
-template <class Impl>
-template <class T>
-Fault
-LSQUnit<Impl>::read(MemReqPtr &req, T &data, int load_idx)
-{
- assert(loadQueue[load_idx]);
-
- assert(!loadQueue[load_idx]->isExecuted());
-
- // Make sure this isn't an uncacheable access
- // A bit of a hackish way to get uncached accesses to work only if they're
- // at the head of the LSQ and are ready to commit (at the head of the ROB
- // too).
- if (req->flags & UNCACHEABLE &&
- (load_idx != loadHead || !loadQueue[load_idx]->reachedCommit)) {
- iewStage->rescheduleMemInst(loadQueue[load_idx]);
- return TheISA::genMachineCheckFault();
- }
-
- // Check the SQ for any previous stores that might lead to forwarding
- int store_idx = loadQueue[load_idx]->sqIdx;
-
- int store_size = 0;
-
- DPRINTF(LSQUnit, "Read called, load idx: %i, store idx: %i, "
- "storeHead: %i addr: %#x\n",
- load_idx, store_idx, storeHead, req->paddr);
-
-#if 0
- if (req->flags & LOCKED) {
- cpu->lockAddr = req->paddr;
- cpu->lockFlag = true;
- }
-#endif
- req->cmd = Read;
- assert(!req->completionEvent);
- req->completionEvent = NULL;
- req->time = curTick;
-
- while (store_idx != -1) {
- // End once we've reached the top of the LSQ
- if (store_idx == storeWBIdx) {
- break;
- }
-
- // Move the index to one younger
- if (--store_idx < 0)
- store_idx += SQEntries;
-
- assert(storeQueue[store_idx].inst);
-
- store_size = storeQueue[store_idx].size;
-
- if (store_size == 0)
- continue;
-
- // Check if the store data is within the lower and upper bounds of
- // addresses that the request needs.
- bool store_has_lower_limit =
- req->vaddr >= storeQueue[store_idx].inst->effAddr;
- bool store_has_upper_limit =
- (req->vaddr + req->size) <= (storeQueue[store_idx].inst->effAddr +
- store_size);
- bool lower_load_has_store_part =
- req->vaddr < (storeQueue[store_idx].inst->effAddr +
- store_size);
- bool upper_load_has_store_part =
- (req->vaddr + req->size) > storeQueue[store_idx].inst->effAddr;
-
- // If the store's data has all of the data needed, we can forward.
- if (store_has_lower_limit && store_has_upper_limit) {
- // Get shift amount for offset into the store's data.
- int shift_amt = req->vaddr & (store_size - 1);
- // @todo: Magic number, assumes byte addressing
- shift_amt = shift_amt << 3;
-
- // Cast this to type T?
- data = storeQueue[store_idx].data >> shift_amt;
-
- assert(!req->data);
- req->data = new uint8_t[64];
-
- memcpy(req->data, &data, req->size);
-
- DPRINTF(LSQUnit, "Forwarding from store idx %i to load to "
- "addr %#x, data %#x\n",
- store_idx, req->vaddr, *(req->data));
-
- typename IEW::LdWritebackEvent *wb =
- new typename IEW::LdWritebackEvent(loadQueue[load_idx],
- iewStage);
-
- // We'll say this has a 1 cycle load-store forwarding latency
- // for now.
- // @todo: Need to make this a parameter.
- wb->schedule(curTick);
-
- // Should keep track of stat for forwarded data
- return NoFault;
- } else if ((store_has_lower_limit && lower_load_has_store_part) ||
- (store_has_upper_limit && upper_load_has_store_part) ||
- (lower_load_has_store_part && upper_load_has_store_part)) {
- // This is the partial store-load forwarding case where a store
- // has only part of the load's data.
-
- // If it's already been written back, then don't worry about
- // stalling on it.
- if (storeQueue[store_idx].completed) {
- continue;
- }
-
- // Must stall load and force it to retry, so long as it's the oldest
- // load that needs to do so.
- if (!stalled ||
- (stalled &&
- loadQueue[load_idx]->seqNum <
- loadQueue[stallingLoadIdx]->seqNum)) {
- stalled = true;
- stallingStoreIsn = storeQueue[store_idx].inst->seqNum;
- stallingLoadIdx = load_idx;
- }
-
- // Tell IQ/mem dep unit that this instruction will need to be
- // rescheduled eventually
- iewStage->rescheduleMemInst(loadQueue[load_idx]);
-
- // Do not generate a writeback event as this instruction is not
- // complete.
- DPRINTF(LSQUnit, "Load-store forwarding mis-match. "
- "Store idx %i to load addr %#x\n",
- store_idx, req->vaddr);
-
- return NoFault;
- }
- }
-
- // If there's no forwarding case, then go access memory
- DynInstPtr inst = loadQueue[load_idx];
-
- DPRINTF(LSQUnit, "Doing functional access for inst [sn:%lli] PC %#x\n",
- loadQueue[load_idx]->seqNum, loadQueue[load_idx]->readPC());
-
- assert(!req->data);
- req->data = new uint8_t[64];
- Fault fault = cpu->read(req, data);
- memcpy(req->data, &data, sizeof(T));
-
- ++usedPorts;
-
- // if we have a cache, do cache access too
- if (fault == NoFault && dcacheInterface) {
- if (dcacheInterface->isBlocked()) {
- // There's an older load that's already going to squash.
- if (isLoadBlocked && blockedLoadSeqNum < inst->seqNum)
- return NoFault;
-
- // Record that the load was blocked due to memory. This
- // load will squash all instructions after it, be
- // refetched, and re-executed.
- isLoadBlocked = true;
- loadBlockedHandled = false;
- blockedLoadSeqNum = inst->seqNum;
- // No fault occurred, even though the interface is blocked.
- return NoFault;
- }
-
- DPRINTF(LSQUnit, "Doing timing access for inst PC %#x\n",
- loadQueue[load_idx]->readPC());
-
- assert(!req->completionEvent);
- req->completionEvent =
- new typename IEW::LdWritebackEvent(loadQueue[load_idx], iewStage);
- MemAccessResult result = dcacheInterface->access(req);
-
- assert(dcacheInterface->doEvents());
-
- if (result != MA_HIT) {
- DPRINTF(LSQUnit, "LSQUnit: D-cache miss!\n");
- DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n",
- inst->seqNum);
- } else {
- DPRINTF(LSQUnit, "LSQUnit: D-cache hit!\n");
- DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n",
- inst->seqNum);
- }
- }
-
- return fault;
-}
-
-template <class Impl>
-template <class T>
-Fault
-LSQUnit<Impl>::write(MemReqPtr &req, T &data, int store_idx)
-{
- assert(storeQueue[store_idx].inst);
-
- DPRINTF(LSQUnit, "Doing write to store idx %i, addr %#x data %#x"
- " | storeHead:%i [sn:%i]\n",
- store_idx, req->paddr, data, storeHead,
- storeQueue[store_idx].inst->seqNum);
-
- storeQueue[store_idx].req = req;
- storeQueue[store_idx].size = sizeof(T);
- storeQueue[store_idx].data = data;
-
- // This function only writes the data to the store queue, so no fault
- // can happen here.
- return NoFault;
-}
-
-#endif // __CPU_O3_LSQ_UNIT_HH__
diff --git a/cpu/o3/lsq_unit_impl.hh b/cpu/o3/lsq_unit_impl.hh
deleted file mode 100644
index 4ee8bb234..000000000
--- a/cpu/o3/lsq_unit_impl.hh
+++ /dev/null
@@ -1,878 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/checker/cpu.hh"
-#include "cpu/o3/lsq_unit.hh"
-#include "base/str.hh"
-
-template <class Impl>
-LSQUnit<Impl>::StoreCompletionEvent::StoreCompletionEvent(int store_idx,
- Event *wb_event,
- LSQUnit<Impl> *lsq_ptr)
- : Event(&mainEventQueue),
- wbEvent(wb_event),
- storeIdx(store_idx),
- lsqPtr(lsq_ptr)
-{
- this->setFlags(Event::AutoDelete);
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::StoreCompletionEvent::process()
-{
- DPRINTF(LSQ, "Cache miss complete for store idx:%i\n", storeIdx);
- DPRINTF(Activity, "Activity: st writeback event idx:%i\n", storeIdx);
-
- //lsqPtr->removeMSHR(lsqPtr->storeQueue[storeIdx].inst->seqNum);
-
- if (lsqPtr->isSwitchedOut()) {
- if (wbEvent)
- delete wbEvent;
-
- return;
- }
-
- lsqPtr->cpu->wakeCPU();
- if (wbEvent) {
- wbEvent->process();
- delete wbEvent;
- }
- lsqPtr->completeStore(storeIdx);
-}
-
-template <class Impl>
-const char *
-LSQUnit<Impl>::StoreCompletionEvent::description()
-{
- return "LSQ store completion event";
-}
-
-template <class Impl>
-LSQUnit<Impl>::LSQUnit()
- : loads(0), stores(0), storesToWB(0), stalled(false), isLoadBlocked(false),
- loadBlockedHandled(false)
-{
-}
-
-template<class Impl>
-void
-LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries,
- unsigned maxSQEntries, unsigned id)
-
-{
- DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
-
- switchedOut = false;
-
- lsqID = id;
-
- // Add 1 for the sentinel entry (they are circular queues).
- LQEntries = maxLQEntries + 1;
- SQEntries = maxSQEntries + 1;
-
- loadQueue.resize(LQEntries);
- storeQueue.resize(SQEntries);
-
- loadHead = loadTail = 0;
-
- storeHead = storeWBIdx = storeTail = 0;
-
- usedPorts = 0;
- cachePorts = params->cachePorts;
-
- dcacheInterface = params->dcacheInterface;
-
- memDepViolator = NULL;
-
- blockedLoadSeqNum = 0;
-}
-
-template<class Impl>
-std::string
-LSQUnit<Impl>::name() const
-{
- if (Impl::MaxThreads == 1) {
- return iewStage->name() + ".lsq";
- } else {
- return iewStage->name() + ".lsq.thread." + to_string(lsqID);
- }
-}
-
-template<class Impl>
-void
-LSQUnit<Impl>::clearLQ()
-{
- loadQueue.clear();
-}
-
-template<class Impl>
-void
-LSQUnit<Impl>::clearSQ()
-{
- storeQueue.clear();
-}
-
-#if 0
-template<class Impl>
-void
-LSQUnit<Impl>::setPageTable(PageTable *pt_ptr)
-{
- DPRINTF(LSQUnit, "Setting the page table pointer.\n");
- pTable = pt_ptr;
-}
-#endif
-
-template<class Impl>
-void
-LSQUnit<Impl>::switchOut()
-{
- switchedOut = true;
- for (int i = 0; i < loadQueue.size(); ++i)
- loadQueue[i] = NULL;
-
- assert(storesToWB == 0);
-
- while (storesToWB > 0 &&
- storeWBIdx != storeTail &&
- storeQueue[storeWBIdx].inst &&
- storeQueue[storeWBIdx].canWB) {
-
- if (storeQueue[storeWBIdx].size == 0 ||
- storeQueue[storeWBIdx].inst->isDataPrefetch() ||
- storeQueue[storeWBIdx].committed ||
- storeQueue[storeWBIdx].req->flags & LOCKED) {
- incrStIdx(storeWBIdx);
-
- continue;
- }
-
- assert(storeQueue[storeWBIdx].req);
- assert(!storeQueue[storeWBIdx].committed);
-
- MemReqPtr req = storeQueue[storeWBIdx].req;
- storeQueue[storeWBIdx].committed = true;
-
- req->cmd = Write;
- req->completionEvent = NULL;
- req->time = curTick;
- assert(!req->data);
- req->data = new uint8_t[64];
- memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size);
-
- DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x "
- "to Addr:%#x, data:%#x [sn:%lli]\n",
- storeWBIdx,storeQueue[storeWBIdx].inst->readPC(),
- req->paddr, *(req->data),
- storeQueue[storeWBIdx].inst->seqNum);
-
- switch(storeQueue[storeWBIdx].size) {
- case 1:
- cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data);
- break;
- case 2:
- cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data);
- break;
- case 4:
- cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data);
- break;
- case 8:
- cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data);
- break;
- default:
- panic("Unexpected store size!\n");
- }
- incrStIdx(storeWBIdx);
- }
-}
-
-template<class Impl>
-void
-LSQUnit<Impl>::takeOverFrom()
-{
- switchedOut = false;
- loads = stores = storesToWB = 0;
-
- loadHead = loadTail = 0;
-
- storeHead = storeWBIdx = storeTail = 0;
-
- usedPorts = 0;
-
- memDepViolator = NULL;
-
- blockedLoadSeqNum = 0;
-
- stalled = false;
- isLoadBlocked = false;
- loadBlockedHandled = false;
-}
-
-template<class Impl>
-void
-LSQUnit<Impl>::resizeLQ(unsigned size)
-{
- unsigned size_plus_sentinel = size + 1;
- assert(size_plus_sentinel >= LQEntries);
-
- if (size_plus_sentinel > LQEntries) {
- while (size_plus_sentinel > loadQueue.size()) {
- DynInstPtr dummy;
- loadQueue.push_back(dummy);
- LQEntries++;
- }
- } else {
- LQEntries = size_plus_sentinel;
- }
-
-}
-
-template<class Impl>
-void
-LSQUnit<Impl>::resizeSQ(unsigned size)
-{
- unsigned size_plus_sentinel = size + 1;
- if (size_plus_sentinel > SQEntries) {
- while (size_plus_sentinel > storeQueue.size()) {
- SQEntry dummy;
- storeQueue.push_back(dummy);
- SQEntries++;
- }
- } else {
- SQEntries = size_plus_sentinel;
- }
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::insert(DynInstPtr &inst)
-{
- assert(inst->isMemRef());
-
- assert(inst->isLoad() || inst->isStore());
-
- if (inst->isLoad()) {
- insertLoad(inst);
- } else {
- insertStore(inst);
- }
-
- inst->setInLSQ();
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::insertLoad(DynInstPtr &load_inst)
-{
- assert((loadTail + 1) % LQEntries != loadHead);
- assert(loads < LQEntries);
-
- DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n",
- load_inst->readPC(), loadTail, load_inst->seqNum);
-
- load_inst->lqIdx = loadTail;
-
- if (stores == 0) {
- load_inst->sqIdx = -1;
- } else {
- load_inst->sqIdx = storeTail;
- }
-
- loadQueue[loadTail] = load_inst;
-
- incrLdIdx(loadTail);
-
- ++loads;
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::insertStore(DynInstPtr &store_inst)
-{
- // Make sure it is not full before inserting an instruction.
- assert((storeTail + 1) % SQEntries != storeHead);
- assert(stores < SQEntries);
-
- DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n",
- store_inst->readPC(), storeTail, store_inst->seqNum);
-
- store_inst->sqIdx = storeTail;
- store_inst->lqIdx = loadTail;
-
- storeQueue[storeTail] = SQEntry(store_inst);
-
- incrStIdx(storeTail);
-
- ++stores;
-}
-
-template <class Impl>
-typename Impl::DynInstPtr
-LSQUnit<Impl>::getMemDepViolator()
-{
- DynInstPtr temp = memDepViolator;
-
- memDepViolator = NULL;
-
- return temp;
-}
-
-template <class Impl>
-unsigned
-LSQUnit<Impl>::numFreeEntries()
-{
- unsigned free_lq_entries = LQEntries - loads;
- unsigned free_sq_entries = SQEntries - stores;
-
- // Both the LQ and SQ entries have an extra dummy entry to differentiate
- // empty/full conditions. Subtract 1 from the free entries.
- if (free_lq_entries < free_sq_entries) {
- return free_lq_entries - 1;
- } else {
- return free_sq_entries - 1;
- }
-}
-
-template <class Impl>
-int
-LSQUnit<Impl>::numLoadsReady()
-{
- int load_idx = loadHead;
- int retval = 0;
-
- while (load_idx != loadTail) {
- assert(loadQueue[load_idx]);
-
- if (loadQueue[load_idx]->readyToIssue()) {
- ++retval;
- }
- }
-
- return retval;
-}
-
-template <class Impl>
-Fault
-LSQUnit<Impl>::executeLoad(DynInstPtr &inst)
-{
- // Execute a specific load.
- Fault load_fault = NoFault;
-
- DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n",
- inst->readPC(),inst->seqNum);
-
-// load_fault = inst->initiateAcc();
- load_fault = inst->execute();
-
- // If the instruction faulted, then we need to send it along to commit
- // without the instruction completing.
- if (load_fault != NoFault) {
- // Send this instruction to commit, also make sure iew stage
- // realizes there is activity.
- iewStage->instToCommit(inst);
- iewStage->activityThisCycle();
- }
-
- return load_fault;
-}
-
-template <class Impl>
-Fault
-LSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
-{
- using namespace TheISA;
- // Make sure that a store exists.
- assert(stores != 0);
-
- int store_idx = store_inst->sqIdx;
-
- DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n",
- store_inst->readPC(), store_inst->seqNum);
-
- // Check the recently completed loads to see if any match this store's
- // address. If so, then we have a memory ordering violation.
- int load_idx = store_inst->lqIdx;
-
- Fault store_fault = store_inst->initiateAcc();
-// Fault store_fault = store_inst->execute();
-
- if (storeQueue[store_idx].size == 0) {
- DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n",
- store_inst->readPC(),store_inst->seqNum);
-
- return store_fault;
- }
-
- assert(store_fault == NoFault);
-
- if (store_inst->isStoreConditional()) {
- // Store conditionals need to set themselves as able to
- // writeback if we haven't had a fault by here.
- storeQueue[store_idx].canWB = true;
-
- ++storesToWB;
- }
-
- if (!memDepViolator) {
- while (load_idx != loadTail) {
- // Really only need to check loads that have actually executed
- // It's safe to check all loads because effAddr is set to
- // InvalAddr when the dyn inst is created.
-
- // @todo: For now this is extra conservative, detecting a
- // violation if the addresses match assuming all accesses
- // are quad word accesses.
-
- // @todo: Fix this, magic number being used here
- if ((loadQueue[load_idx]->effAddr >> 8) ==
- (store_inst->effAddr >> 8)) {
- // A load incorrectly passed this store. Squash and refetch.
- // For now return a fault to show that it was unsuccessful.
- memDepViolator = loadQueue[load_idx];
-
- return genMachineCheckFault();
- }
-
- incrLdIdx(load_idx);
- }
-
- // If we've reached this point, there was no violation.
- memDepViolator = NULL;
- }
-
- return store_fault;
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::commitLoad()
-{
- assert(loadQueue[loadHead]);
-
- DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n",
- loadQueue[loadHead]->readPC());
-
- loadQueue[loadHead] = NULL;
-
- incrLdIdx(loadHead);
-
- --loads;
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst)
-{
- assert(loads == 0 || loadQueue[loadHead]);
-
- while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) {
- commitLoad();
- }
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst)
-{
- assert(stores == 0 || storeQueue[storeHead].inst);
-
- int store_idx = storeHead;
-
- while (store_idx != storeTail) {
- assert(storeQueue[store_idx].inst);
- // Mark any stores that are now committed and have not yet
- // been marked as able to write back.
- if (!storeQueue[store_idx].canWB) {
- if (storeQueue[store_idx].inst->seqNum > youngest_inst) {
- break;
- }
- DPRINTF(LSQUnit, "Marking store as able to write back, PC "
- "%#x [sn:%lli]\n",
- storeQueue[store_idx].inst->readPC(),
- storeQueue[store_idx].inst->seqNum);
-
- storeQueue[store_idx].canWB = true;
-
- ++storesToWB;
- }
-
- incrStIdx(store_idx);
- }
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::writebackStores()
-{
- while (storesToWB > 0 &&
- storeWBIdx != storeTail &&
- storeQueue[storeWBIdx].inst &&
- storeQueue[storeWBIdx].canWB &&
- usedPorts < cachePorts) {
-
- // Store didn't write any data so no need to write it back to
- // memory.
- if (storeQueue[storeWBIdx].size == 0) {
- completeStore(storeWBIdx);
-
- incrStIdx(storeWBIdx);
-
- continue;
- }
-
- if (dcacheInterface && dcacheInterface->isBlocked()) {
- DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
- " is blocked!\n");
- break;
- }
-
- ++usedPorts;
-
- if (storeQueue[storeWBIdx].inst->isDataPrefetch()) {
- incrStIdx(storeWBIdx);
-
- continue;
- }
-
- assert(storeQueue[storeWBIdx].req);
- assert(!storeQueue[storeWBIdx].committed);
-
- MemReqPtr req = storeQueue[storeWBIdx].req;
- storeQueue[storeWBIdx].committed = true;
-
- req->cmd = Write;
- req->completionEvent = NULL;
- req->time = curTick;
- assert(!req->data);
- req->data = new uint8_t[64];
- memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size);
-
- DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x "
- "to Addr:%#x, data:%#x [sn:%lli]\n",
- storeWBIdx,storeQueue[storeWBIdx].inst->readPC(),
- req->paddr, *(req->data),
- storeQueue[storeWBIdx].inst->seqNum);
-
- switch(storeQueue[storeWBIdx].size) {
- case 1:
- cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data);
- break;
- case 2:
- cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data);
- break;
- case 4:
- cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data);
- break;
- case 8:
- cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data);
- break;
- default:
- panic("Unexpected store size!\n");
- }
-
- // Stores other than store conditionals are completed at this
- // time. Mark them as completed and, if we have a checker,
- // tell it that the instruction is completed.
- // @todo: Figure out what time I can say stores are complete in
- // the timing memory.
- if (!(req->flags & LOCKED)) {
- storeQueue[storeWBIdx].inst->setCompleted();
- if (cpu->checker) {
- cpu->checker->tick(storeQueue[storeWBIdx].inst);
- }
- }
-
- if (dcacheInterface) {
- assert(!req->completionEvent);
- StoreCompletionEvent *store_event = new
- StoreCompletionEvent(storeWBIdx, NULL, this);
- req->completionEvent = store_event;
-
- MemAccessResult result = dcacheInterface->access(req);
-
- if (isStalled() &&
- storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) {
- DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
- "load idx:%i\n",
- stallingStoreIsn, stallingLoadIdx);
- stalled = false;
- stallingStoreIsn = 0;
- iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
- }
-
- typename IEW::LdWritebackEvent *wb = NULL;
- if (req->flags & LOCKED) {
- // Stx_C should not generate a system port transaction
- // if it misses in the cache, but that might be hard
- // to accomplish without explicit cache support.
- wb = new typename
- IEW::LdWritebackEvent(storeQueue[storeWBIdx].inst,
- iewStage);
- store_event->wbEvent = wb;
- }
-
- if (result != MA_HIT && dcacheInterface->doEvents()) {
- DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n",
- storeWBIdx);
-
- DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n",
- storeQueue[storeWBIdx].inst->seqNum);
-
- //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum);
-
- //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size());
-
- // @todo: Increment stat here.
- } else {
- DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n",
- storeWBIdx);
-
- DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
- storeQueue[storeWBIdx].inst->seqNum);
- }
-
- incrStIdx(storeWBIdx);
- } else {
- panic("Must HAVE DCACHE!!!!!\n");
- }
- }
-
- // Not sure this should set it to 0.
- usedPorts = 0;
-
- assert(stores >= 0 && storesToWB >= 0);
-}
-
-/*template <class Impl>
-void
-LSQUnit<Impl>::removeMSHR(InstSeqNum seqNum)
-{
- list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(),
- mshrSeqNums.end(),
- seqNum);
-
- if (mshr_it != mshrSeqNums.end()) {
- mshrSeqNums.erase(mshr_it);
- DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size());
- }
-}*/
-
-template <class Impl>
-void
-LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
-{
- DPRINTF(LSQUnit, "Squashing until [sn:%lli]!"
- "(Loads:%i Stores:%i)\n", squashed_num, loads, stores);
-
- int load_idx = loadTail;
- decrLdIdx(load_idx);
-
- while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) {
- DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, "
- "[sn:%lli]\n",
- loadQueue[load_idx]->readPC(),
- loadQueue[load_idx]->seqNum);
-
- if (isStalled() && load_idx == stallingLoadIdx) {
- stalled = false;
- stallingStoreIsn = 0;
- stallingLoadIdx = 0;
- }
-
- // Clear the smart pointer to make sure it is decremented.
- loadQueue[load_idx]->squashed = true;
- loadQueue[load_idx] = NULL;
- --loads;
-
- // Inefficient!
- loadTail = load_idx;
-
- decrLdIdx(load_idx);
- }
-
- if (isLoadBlocked) {
- if (squashed_num < blockedLoadSeqNum) {
- isLoadBlocked = false;
- loadBlockedHandled = false;
- blockedLoadSeqNum = 0;
- }
- }
-
- int store_idx = storeTail;
- decrStIdx(store_idx);
-
- while (stores != 0 &&
- storeQueue[store_idx].inst->seqNum > squashed_num) {
- // Instructions marked as can WB are already committed.
- if (storeQueue[store_idx].canWB) {
- break;
- }
-
- DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, "
- "idx:%i [sn:%lli]\n",
- storeQueue[store_idx].inst->readPC(),
- store_idx, storeQueue[store_idx].inst->seqNum);
-
- // I don't think this can happen. It should have been cleared
- // by the stalling load.
- if (isStalled() &&
- storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
- panic("Is stalled should have been cleared by stalling load!\n");
- stalled = false;
- stallingStoreIsn = 0;
- }
-
- // Clear the smart pointer to make sure it is decremented.
- storeQueue[store_idx].inst->squashed = true;
- storeQueue[store_idx].inst = NULL;
- storeQueue[store_idx].canWB = 0;
-
- if (storeQueue[store_idx].req) {
- // There should not be a completion event if the store has
- // not yet committed.
- assert(!storeQueue[store_idx].req->completionEvent);
- }
-
- storeQueue[store_idx].req = NULL;
- --stores;
-
- // Inefficient!
- storeTail = store_idx;
-
- decrStIdx(store_idx);
- }
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::completeStore(int store_idx)
-{
- assert(storeQueue[store_idx].inst);
- storeQueue[store_idx].completed = true;
- --storesToWB;
- // A bit conservative because a store completion may not free up entries,
- // but hopefully avoids two store completions in one cycle from making
- // the CPU tick twice.
- cpu->activityThisCycle();
-
- if (store_idx == storeHead) {
- do {
- incrStIdx(storeHead);
-
- --stores;
- } while (storeQueue[storeHead].completed &&
- storeHead != storeTail);
-
- iewStage->updateLSQNextCycle = true;
- }
-
- DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head "
- "idx:%i\n",
- storeQueue[store_idx].inst->seqNum, store_idx, storeHead);
-
- if (isStalled() &&
- storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
- DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
- "load idx:%i\n",
- stallingStoreIsn, stallingLoadIdx);
- stalled = false;
- stallingStoreIsn = 0;
- iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
- }
-
- storeQueue[store_idx].inst->setCompleted();
-
- // Tell the checker we've completed this instruction. Some stores
- // may get reported twice to the checker, but the checker can
- // handle that case.
- if (cpu->checker) {
- cpu->checker->tick(storeQueue[store_idx].inst);
- }
-}
-
-template <class Impl>
-inline void
-LSQUnit<Impl>::incrStIdx(int &store_idx)
-{
- if (++store_idx >= SQEntries)
- store_idx = 0;
-}
-
-template <class Impl>
-inline void
-LSQUnit<Impl>::decrStIdx(int &store_idx)
-{
- if (--store_idx < 0)
- store_idx += SQEntries;
-}
-
-template <class Impl>
-inline void
-LSQUnit<Impl>::incrLdIdx(int &load_idx)
-{
- if (++load_idx >= LQEntries)
- load_idx = 0;
-}
-
-template <class Impl>
-inline void
-LSQUnit<Impl>::decrLdIdx(int &load_idx)
-{
- if (--load_idx < 0)
- load_idx += LQEntries;
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::dumpInsts()
-{
- cprintf("Load store queue: Dumping instructions.\n");
- cprintf("Load queue size: %i\n", loads);
- cprintf("Load queue: ");
-
- int load_idx = loadHead;
-
- while (load_idx != loadTail && loadQueue[load_idx]) {
- cprintf("%#x ", loadQueue[load_idx]->readPC());
-
- incrLdIdx(load_idx);
- }
-
- cprintf("Store queue size: %i\n", stores);
- cprintf("Store queue: ");
-
- int store_idx = storeHead;
-
- while (store_idx != storeTail && storeQueue[store_idx].inst) {
- cprintf("%#x ", storeQueue[store_idx].inst->readPC());
-
- incrStIdx(store_idx);
- }
-
- cprintf("\n");
-}
diff --git a/cpu/o3/mem_dep_unit.cc b/cpu/o3/mem_dep_unit.cc
deleted file mode 100644
index ccdd1a515..000000000
--- a/cpu/o3/mem_dep_unit.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/o3/alpha_dyn_inst.hh"
-#include "cpu/o3/alpha_impl.hh"
-#include "cpu/o3/store_set.hh"
-#include "cpu/o3/mem_dep_unit_impl.hh"
-
-// Force instantation of memory dependency unit using store sets and
-// AlphaSimpleImpl.
-template class MemDepUnit<StoreSet, AlphaSimpleImpl>;
-
-template <>
-int
-MemDepUnit<StoreSet, AlphaSimpleImpl>::MemDepEntry::memdep_count = 0;
-template <>
-int
-MemDepUnit<StoreSet, AlphaSimpleImpl>::MemDepEntry::memdep_insert = 0;
-template <>
-int
-MemDepUnit<StoreSet, AlphaSimpleImpl>::MemDepEntry::memdep_erase = 0;
diff --git a/cpu/o3/mem_dep_unit.hh b/cpu/o3/mem_dep_unit.hh
deleted file mode 100644
index bb0406de1..000000000
--- a/cpu/o3/mem_dep_unit.hh
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_MEM_DEP_UNIT_HH__
-#define __CPU_O3_MEM_DEP_UNIT_HH__
-
-#include <list>
-#include <set>
-
-#include "base/hashmap.hh"
-#include "base/refcnt.hh"
-#include "base/statistics.hh"
-#include "cpu/inst_seq.hh"
-
-struct SNHash {
- size_t operator() (const InstSeqNum &seq_num) const {
- unsigned a = (unsigned)seq_num;
- unsigned hash = (((a >> 14) ^ ((a >> 2) & 0xffff))) & 0x7FFFFFFF;
-
- return hash;
- }
-};
-
-template <class Impl>
-class InstructionQueue;
-
-/**
- * Memory dependency unit class. This holds the memory dependence predictor.
- * As memory operations are issued to the IQ, they are also issued to this
- * unit, which then looks up the prediction as to what they are dependent
- * upon. This unit must be checked prior to a memory operation being able
- * to issue. Although this is templated, it's somewhat hard to make a generic
- * memory dependence unit. This one is mostly for store sets; it will be
- * quite limited in what other memory dependence predictions it can also
- * utilize. Thus this class should be most likely be rewritten for other
- * dependence prediction schemes.
- */
-template <class MemDepPred, class Impl>
-class MemDepUnit {
- public:
- typedef typename Impl::Params Params;
- typedef typename Impl::DynInstPtr DynInstPtr;
-
- /** Empty constructor. Must call init() prior to using in this case. */
- MemDepUnit() {}
-
- /** Constructs a MemDepUnit with given parameters. */
- MemDepUnit(Params *params);
-
- /** Frees up any memory allocated. */
- ~MemDepUnit();
-
- /** Returns the name of the memory dependence unit. */
- std::string name() const;
-
- /** Initializes the unit with parameters and a thread id. */
- void init(Params *params, int tid);
-
- /** Registers statistics. */
- void regStats();
-
- /** Switches out the memory dependence predictor. */
- void switchOut();
-
- /** Takes over from another CPU's thread. */
- void takeOverFrom();
-
- /** Sets the pointer to the IQ. */
- void setIQ(InstructionQueue<Impl> *iq_ptr);
-
- /** Inserts a memory instruction. */
- void insert(DynInstPtr &inst);
-
- /** Inserts a non-speculative memory instruction. */
- void insertNonSpec(DynInstPtr &inst);
-
- /** Inserts a barrier instruction. */
- void insertBarrier(DynInstPtr &barr_inst);
-
- /** Indicate that an instruction has its registers ready. */
- void regsReady(DynInstPtr &inst);
-
- /** Indicate that a non-speculative instruction is ready. */
- void nonSpecInstReady(DynInstPtr &inst);
-
- /** Reschedules an instruction to be re-executed. */
- void reschedule(DynInstPtr &inst);
-
- /** Replays all instructions that have been rescheduled by moving them to
- * the ready list.
- */
- void replay(DynInstPtr &inst);
-
- /** Completes a memory instruction. */
- void completed(DynInstPtr &inst);
-
- /** Completes a barrier instruction. */
- void completeBarrier(DynInstPtr &inst);
-
- /** Wakes any dependents of a memory instruction. */
- void wakeDependents(DynInstPtr &inst);
-
- /** Squashes all instructions up until a given sequence number for a
- * specific thread.
- */
- void squash(const InstSeqNum &squashed_num, unsigned tid);
-
- /** Indicates an ordering violation between a store and a younger load. */
- void violation(DynInstPtr &store_inst, DynInstPtr &violating_load);
-
- /** Issues the given instruction */
- void issue(DynInstPtr &inst);
-
- /** Debugging function to dump the lists of instructions. */
- void dumpLists();
-
- private:
- typedef typename std::list<DynInstPtr>::iterator ListIt;
-
- class MemDepEntry;
-
- typedef RefCountingPtr<MemDepEntry> MemDepEntryPtr;
-
- /** Memory dependence entries that track memory operations, marking
- * when the instruction is ready to execute and what instructions depend
- * upon it.
- */
- class MemDepEntry : public RefCounted {
- public:
- /** Constructs a memory dependence entry. */
- MemDepEntry(DynInstPtr &new_inst)
- : inst(new_inst), regsReady(false), memDepReady(false),
- completed(false), squashed(false)
- {
-#ifdef DEBUG
- ++memdep_count;
-
- DPRINTF(MemDepUnit, "Memory dependency entry created. "
- "memdep_count=%i\n", memdep_count);
-#endif
- }
-
- /** Frees any pointers. */
- ~MemDepEntry()
- {
- for (int i = 0; i < dependInsts.size(); ++i) {
- dependInsts[i] = NULL;
- }
-#ifdef DEBUG
- --memdep_count;
-
- DPRINTF(MemDepUnit, "Memory dependency entry deleted. "
- "memdep_count=%i\n", memdep_count);
-#endif
- }
-
- /** Returns the name of the memory dependence entry. */
- std::string name() const { return "memdepentry"; }
-
- /** The instruction being tracked. */
- DynInstPtr inst;
-
- /** The iterator to the instruction's location inside the list. */
- ListIt listIt;
-
- /** A vector of any dependent instructions. */
- std::vector<MemDepEntryPtr> dependInsts;
-
- /** If the registers are ready or not. */
- bool regsReady;
- /** If all memory dependencies have been satisfied. */
- bool memDepReady;
- /** If the instruction is completed. */
- bool completed;
- /** If the instruction is squashed. */
- bool squashed;
-
- /** For debugging. */
-#ifdef DEBUG
- static int memdep_count;
- static int memdep_insert;
- static int memdep_erase;
-#endif
- };
-
- /** Finds the memory dependence entry in the hash map. */
- inline MemDepEntryPtr &findInHash(const DynInstPtr &inst);
-
- /** Moves an entry to the ready list. */
- inline void moveToReady(MemDepEntryPtr &ready_inst_entry);
-
- typedef m5::hash_map<InstSeqNum, MemDepEntryPtr, SNHash> MemDepHash;
-
- typedef typename MemDepHash::iterator MemDepHashIt;
-
- /** A hash map of all memory dependence entries. */
- MemDepHash memDepHash;
-
- /** A list of all instructions in the memory dependence unit. */
- std::list<DynInstPtr> instList[Impl::MaxThreads];
-
- /** A list of all instructions that are going to be replayed. */
- std::list<DynInstPtr> instsToReplay;
-
- /** The memory dependence predictor. It is accessed upon new
- * instructions being added to the IQ, and responds by telling
- * this unit what instruction the newly added instruction is dependent
- * upon.
- */
- MemDepPred depPred;
-
- /** Is there an outstanding load barrier that loads must wait on. */
- bool loadBarrier;
- /** The sequence number of the load barrier. */
- InstSeqNum loadBarrierSN;
- /** Is there an outstanding store barrier that loads must wait on. */
- bool storeBarrier;
- /** The sequence number of the store barrier. */
- InstSeqNum storeBarrierSN;
-
- /** Pointer to the IQ. */
- InstructionQueue<Impl> *iqPtr;
-
- /** The thread id of this memory dependence unit. */
- int id;
-
- /** Stat for number of inserted loads. */
- Stats::Scalar<> insertedLoads;
- /** Stat for number of inserted stores. */
- Stats::Scalar<> insertedStores;
- /** Stat for number of conflicting loads that had to wait for a store. */
- Stats::Scalar<> conflictingLoads;
- /** Stat for number of conflicting stores that had to wait for a store. */
- Stats::Scalar<> conflictingStores;
-};
-
-#endif // __CPU_O3_MEM_DEP_UNIT_HH__
diff --git a/cpu/o3/mem_dep_unit_impl.hh b/cpu/o3/mem_dep_unit_impl.hh
deleted file mode 100644
index 595e9293f..000000000
--- a/cpu/o3/mem_dep_unit_impl.hh
+++ /dev/null
@@ -1,555 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <map>
-
-#include "cpu/o3/inst_queue.hh"
-#include "cpu/o3/mem_dep_unit.hh"
-
-template <class MemDepPred, class Impl>
-MemDepUnit<MemDepPred, Impl>::MemDepUnit(Params *params)
- : depPred(params->SSITSize, params->LFSTSize), loadBarrier(false),
- loadBarrierSN(0), storeBarrier(false), storeBarrierSN(0), iqPtr(NULL)
-{
- DPRINTF(MemDepUnit, "Creating MemDepUnit object.\n");
-}
-
-template <class MemDepPred, class Impl>
-MemDepUnit<MemDepPred, Impl>::~MemDepUnit()
-{
- for (int tid=0; tid < Impl::MaxThreads; tid++) {
-
- ListIt inst_list_it = instList[tid].begin();
-
- MemDepHashIt hash_it;
-
- while (!instList[tid].empty()) {
- hash_it = memDepHash.find((*inst_list_it)->seqNum);
-
- assert(hash_it != memDepHash.end());
-
- memDepHash.erase(hash_it);
-
- instList[tid].erase(inst_list_it++);
- }
- }
-
- assert(MemDepEntry::memdep_count == 0);
-}
-
-template <class MemDepPred, class Impl>
-std::string
-MemDepUnit<MemDepPred, Impl>::name() const
-{
- return "memdepunit";
-}
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::init(Params *params, int tid)
-{
- DPRINTF(MemDepUnit, "Creating MemDepUnit %i object.\n",tid);
-
- id = tid;
-
- depPred.init(params->SSITSize, params->LFSTSize);
-}
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::regStats()
-{
- insertedLoads
- .name(name() + ".memDep.insertedLoads")
- .desc("Number of loads inserted to the mem dependence unit.");
-
- insertedStores
- .name(name() + ".memDep.insertedStores")
- .desc("Number of stores inserted to the mem dependence unit.");
-
- conflictingLoads
- .name(name() + ".memDep.conflictingLoads")
- .desc("Number of conflicting loads.");
-
- conflictingStores
- .name(name() + ".memDep.conflictingStores")
- .desc("Number of conflicting stores.");
-}
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::switchOut()
-{
- // Clear any state.
- for (int i = 0; i < Impl::MaxThreads; ++i) {
- instList[i].clear();
- }
- instsToReplay.clear();
- memDepHash.clear();
-}
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::takeOverFrom()
-{
- // Be sure to reset all state.
- loadBarrier = storeBarrier = false;
- loadBarrierSN = storeBarrierSN = 0;
- depPred.clear();
-}
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::setIQ(InstructionQueue<Impl> *iq_ptr)
-{
- iqPtr = iq_ptr;
-}
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst)
-{
- unsigned tid = inst->threadNumber;
-
- MemDepEntryPtr inst_entry = new MemDepEntry(inst);
-
- // Add the MemDepEntry to the hash.
- memDepHash.insert(
- std::pair<InstSeqNum, MemDepEntryPtr>(inst->seqNum, inst_entry));
- MemDepEntry::memdep_insert++;
-
- instList[tid].push_back(inst);
-
- inst_entry->listIt = --(instList[tid].end());
-
- // Check any barriers and the dependence predictor for any
- // producing memrefs/stores.
- InstSeqNum producing_store;
- if (inst->isLoad() && loadBarrier) {
- producing_store = loadBarrierSN;
- } else if (inst->isStore() && storeBarrier) {
- producing_store = storeBarrierSN;
- } else {
- producing_store = depPred.checkInst(inst->readPC());
- }
-
- MemDepEntryPtr store_entry = NULL;
-
- // If there is a producing store, try to find the entry.
- if (producing_store != 0) {
- MemDepHashIt hash_it = memDepHash.find(producing_store);
-
- if (hash_it != memDepHash.end()) {
- store_entry = (*hash_it).second;
- }
- }
-
- // If no store entry, then instruction can issue as soon as the registers
- // are ready.
- if (!store_entry) {
- DPRINTF(MemDepUnit, "No dependency for inst PC "
- "%#x [sn:%lli].\n", inst->readPC(), inst->seqNum);
-
- inst_entry->memDepReady = true;
-
- if (inst->readyToIssue()) {
- inst_entry->regsReady = true;
-
- moveToReady(inst_entry);
- }
- } else {
- // Otherwise make the instruction dependent on the store/barrier.
- DPRINTF(MemDepUnit, "Adding to dependency list; "
- "inst PC %#x is dependent on [sn:%lli].\n",
- inst->readPC(), producing_store);
-
- if (inst->readyToIssue()) {
- inst_entry->regsReady = true;
- }
-
- // Add this instruction to the list of dependents.
- store_entry->dependInsts.push_back(inst_entry);
-
- if (inst->isLoad()) {
- ++conflictingLoads;
- } else {
- ++conflictingStores;
- }
- }
-
- if (inst->isStore()) {
- DPRINTF(MemDepUnit, "Inserting store PC %#x [sn:%lli].\n",
- inst->readPC(), inst->seqNum);
-
- depPred.insertStore(inst->readPC(), inst->seqNum, inst->threadNumber);
-
- ++insertedStores;
- } else if (inst->isLoad()) {
- ++insertedLoads;
- } else {
- panic("Unknown type! (most likely a barrier).");
- }
-}
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::insertNonSpec(DynInstPtr &inst)
-{
- unsigned tid = inst->threadNumber;
-
- MemDepEntryPtr inst_entry = new MemDepEntry(inst);
-
- // Insert the MemDepEntry into the hash.
- memDepHash.insert(
- std::pair<InstSeqNum, MemDepEntryPtr>(inst->seqNum, inst_entry));
- MemDepEntry::memdep_insert++;
-
- // Add the instruction to the list.
- instList[tid].push_back(inst);
-
- inst_entry->listIt = --(instList[tid].end());
-
- // Might want to turn this part into an inline function or something.
- // It's shared between both insert functions.
- if (inst->isStore()) {
- DPRINTF(MemDepUnit, "Inserting store PC %#x [sn:%lli].\n",
- inst->readPC(), inst->seqNum);
-
- depPred.insertStore(inst->readPC(), inst->seqNum, inst->threadNumber);
-
- ++insertedStores;
- } else if (inst->isLoad()) {
- ++insertedLoads;
- } else {
- panic("Unknown type! (most likely a barrier).");
- }
-}
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::insertBarrier(DynInstPtr &barr_inst)
-{
- InstSeqNum barr_sn = barr_inst->seqNum;
- // Memory barriers block loads and stores, write barriers only stores.
- if (barr_inst->isMemBarrier()) {
- loadBarrier = true;
- loadBarrierSN = barr_sn;
- storeBarrier = true;
- storeBarrierSN = barr_sn;
- DPRINTF(MemDepUnit, "Inserted a memory barrier\n");
- } else if (barr_inst->isWriteBarrier()) {
- storeBarrier = true;
- storeBarrierSN = barr_sn;
- DPRINTF(MemDepUnit, "Inserted a write barrier\n");
- }
-
- unsigned tid = barr_inst->threadNumber;
-
- MemDepEntryPtr inst_entry = new MemDepEntry(barr_inst);
-
- // Add the MemDepEntry to the hash.
- memDepHash.insert(
- std::pair<InstSeqNum, MemDepEntryPtr>(barr_sn, inst_entry));
- MemDepEntry::memdep_insert++;
-
- // Add the instruction to the instruction list.
- instList[tid].push_back(barr_inst);
-
- inst_entry->listIt = --(instList[tid].end());
-}
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::regsReady(DynInstPtr &inst)
-{
- DPRINTF(MemDepUnit, "Marking registers as ready for "
- "instruction PC %#x [sn:%lli].\n",
- inst->readPC(), inst->seqNum);
-
- MemDepEntryPtr inst_entry = findInHash(inst);
-
- inst_entry->regsReady = true;
-
- if (inst_entry->memDepReady) {
- DPRINTF(MemDepUnit, "Instruction has its memory "
- "dependencies resolved, adding it to the ready list.\n");
-
- moveToReady(inst_entry);
- } else {
- DPRINTF(MemDepUnit, "Instruction still waiting on "
- "memory dependency.\n");
- }
-}
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::nonSpecInstReady(DynInstPtr &inst)
-{
- DPRINTF(MemDepUnit, "Marking non speculative "
- "instruction PC %#x as ready [sn:%lli].\n",
- inst->readPC(), inst->seqNum);
-
- MemDepEntryPtr inst_entry = findInHash(inst);
-
- moveToReady(inst_entry);
-}
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::reschedule(DynInstPtr &inst)
-{
- instsToReplay.push_back(inst);
-}
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::replay(DynInstPtr &inst)
-{
- DynInstPtr temp_inst;
- bool found_inst = false;
-
- // For now this replay function replays all waiting memory ops.
- while (!instsToReplay.empty()) {
- temp_inst = instsToReplay.front();
-
- MemDepEntryPtr inst_entry = findInHash(temp_inst);
-
- DPRINTF(MemDepUnit, "Replaying mem instruction PC %#x "
- "[sn:%lli].\n",
- temp_inst->readPC(), temp_inst->seqNum);
-
- moveToReady(inst_entry);
-
- if (temp_inst == inst) {
- found_inst = true;
- }
-
- instsToReplay.pop_front();
- }
-
- assert(found_inst);
-}
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::completed(DynInstPtr &inst)
-{
- DPRINTF(MemDepUnit, "Completed mem instruction PC %#x "
- "[sn:%lli].\n",
- inst->readPC(), inst->seqNum);
-
- unsigned tid = inst->threadNumber;
-
- // Remove the instruction from the hash and the list.
- MemDepHashIt hash_it = memDepHash.find(inst->seqNum);
-
- assert(hash_it != memDepHash.end());
-
- instList[tid].erase((*hash_it).second->listIt);
-
- (*hash_it).second = NULL;
-
- memDepHash.erase(hash_it);
- MemDepEntry::memdep_erase++;
-}
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::completeBarrier(DynInstPtr &inst)
-{
- wakeDependents(inst);
- completed(inst);
-
- InstSeqNum barr_sn = inst->seqNum;
-
- if (inst->isMemBarrier()) {
- assert(loadBarrier && storeBarrier);
- if (loadBarrierSN == barr_sn)
- loadBarrier = false;
- if (storeBarrierSN == barr_sn)
- storeBarrier = false;
- } else if (inst->isWriteBarrier()) {
- assert(storeBarrier);
- if (storeBarrierSN == barr_sn)
- storeBarrier = false;
- }
-}
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::wakeDependents(DynInstPtr &inst)
-{
- // Only stores and barriers have dependents.
- if (!inst->isStore() && !inst->isMemBarrier() && !inst->isWriteBarrier()) {
- return;
- }
-
- MemDepEntryPtr inst_entry = findInHash(inst);
-
- for (int i = 0; i < inst_entry->dependInsts.size(); ++i ) {
- MemDepEntryPtr woken_inst = inst_entry->dependInsts[i];
-
- if (!woken_inst->inst) {
- // Potentially removed mem dep entries could be on this list
- continue;
- }
-
- DPRINTF(MemDepUnit, "Waking up a dependent inst, "
- "[sn:%lli].\n",
- woken_inst->inst->seqNum);
-
- if (woken_inst->regsReady && !woken_inst->squashed) {
- moveToReady(woken_inst);
- } else {
- woken_inst->memDepReady = true;
- }
- }
-
- inst_entry->dependInsts.clear();
-}
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::squash(const InstSeqNum &squashed_num,
- unsigned tid)
-{
- if (!instsToReplay.empty()) {
- ListIt replay_it = instsToReplay.begin();
- while (replay_it != instsToReplay.end()) {
- if ((*replay_it)->threadNumber == tid &&
- (*replay_it)->seqNum > squashed_num) {
- instsToReplay.erase(replay_it++);
- } else {
- ++replay_it;
- }
- }
- }
-
- ListIt squash_it = instList[tid].end();
- --squash_it;
-
- MemDepHashIt hash_it;
-
- while (!instList[tid].empty() &&
- (*squash_it)->seqNum > squashed_num) {
-
- DPRINTF(MemDepUnit, "Squashing inst [sn:%lli]\n",
- (*squash_it)->seqNum);
-
- hash_it = memDepHash.find((*squash_it)->seqNum);
-
- assert(hash_it != memDepHash.end());
-
- (*hash_it).second->squashed = true;
-
- (*hash_it).second = NULL;
-
- memDepHash.erase(hash_it);
- MemDepEntry::memdep_erase++;
-
- instList[tid].erase(squash_it--);
- }
-
- // Tell the dependency predictor to squash as well.
- depPred.squash(squashed_num, tid);
-}
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::violation(DynInstPtr &store_inst,
- DynInstPtr &violating_load)
-{
- DPRINTF(MemDepUnit, "Passing violating PCs to store sets,"
- " load: %#x, store: %#x\n", violating_load->readPC(),
- store_inst->readPC());
- // Tell the memory dependence unit of the violation.
- depPred.violation(violating_load->readPC(), store_inst->readPC());
-}
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::issue(DynInstPtr &inst)
-{
- DPRINTF(MemDepUnit, "Issuing instruction PC %#x [sn:%lli].\n",
- inst->readPC(), inst->seqNum);
-
- depPred.issued(inst->readPC(), inst->seqNum, inst->isStore());
-}
-
-template <class MemDepPred, class Impl>
-inline typename MemDepUnit<MemDepPred,Impl>::MemDepEntryPtr &
-MemDepUnit<MemDepPred, Impl>::findInHash(const DynInstPtr &inst)
-{
- MemDepHashIt hash_it = memDepHash.find(inst->seqNum);
-
- assert(hash_it != memDepHash.end());
-
- return (*hash_it).second;
-}
-
-template <class MemDepPred, class Impl>
-inline void
-MemDepUnit<MemDepPred, Impl>::moveToReady(MemDepEntryPtr &woken_inst_entry)
-{
- DPRINTF(MemDepUnit, "Adding instruction [sn:%lli] "
- "to the ready list.\n", woken_inst_entry->inst->seqNum);
-
- assert(!woken_inst_entry->squashed);
-
- iqPtr->addReadyMemInst(woken_inst_entry->inst);
-}
-
-
-template <class MemDepPred, class Impl>
-void
-MemDepUnit<MemDepPred, Impl>::dumpLists()
-{
- for (unsigned tid=0; tid < Impl::MaxThreads; tid++) {
- cprintf("Instruction list %i size: %i\n",
- tid, instList[tid].size());
-
- ListIt inst_list_it = instList[tid].begin();
- int num = 0;
-
- while (inst_list_it != instList[tid].end()) {
- cprintf("Instruction:%i\nPC:%#x\n[sn:%i]\n[tid:%i]\nIssued:%i\n"
- "Squashed:%i\n\n",
- num, (*inst_list_it)->readPC(),
- (*inst_list_it)->seqNum,
- (*inst_list_it)->threadNumber,
- (*inst_list_it)->isIssued(),
- (*inst_list_it)->isSquashed());
- inst_list_it++;
- ++num;
- }
- }
-
- cprintf("Memory dependence hash size: %i\n", memDepHash.size());
-
- cprintf("Memory dependence entries: %i\n", MemDepEntry::memdep_count);
-}
diff --git a/cpu/o3/ras.cc b/cpu/o3/ras.cc
deleted file mode 100644
index 0b3ea4918..000000000
--- a/cpu/o3/ras.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/o3/ras.hh"
-
-void
-ReturnAddrStack::init(unsigned _numEntries)
-{
- numEntries = _numEntries;
- usedEntries = 0;
- tos = 0;
-
- addrStack.resize(numEntries);
-
- for (int i = 0; i < numEntries; ++i)
- addrStack[i] = 0;
-}
-
-void
-ReturnAddrStack::reset()
-{
- usedEntries = 0;
- tos = 0;
- for (int i = 0; i < numEntries; ++i)
- addrStack[i] = 0;
-}
-
-void
-ReturnAddrStack::push(const Addr &return_addr)
-{
- incrTos();
-
- addrStack[tos] = return_addr;
-
- if (usedEntries != numEntries) {
- ++usedEntries;
- }
-}
-
-void
-ReturnAddrStack::pop()
-{
- if (usedEntries > 0) {
- --usedEntries;
- }
-
- decrTos();
-}
-
-void
-ReturnAddrStack::restore(unsigned top_entry_idx,
- const Addr &restored_target)
-{
- tos = top_entry_idx;
-
- addrStack[tos] = restored_target;
-}
diff --git a/cpu/o3/ras.hh b/cpu/o3/ras.hh
deleted file mode 100644
index 27e7c2df4..000000000
--- a/cpu/o3/ras.hh
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_RAS_HH__
-#define __CPU_O3_RAS_HH__
-
-// For Addr type.
-#include "arch/isa_traits.hh"
-#include <vector>
-
-/** Return address stack class, implements a simple RAS. */
-class ReturnAddrStack
-{
- public:
- /** Creates a return address stack, but init() must be called prior to
- * use.
- */
- ReturnAddrStack() {}
-
- /** Initializes RAS with a specified number of entries.
- * @param numEntries Number of entries in the RAS.
- */
- void init(unsigned numEntries);
-
- void reset();
-
- /** Returns the top address on the RAS. */
- Addr top()
- { return addrStack[tos]; }
-
- /** Returns the index of the top of the RAS. */
- unsigned topIdx()
- { return tos; }
-
- /** Pushes an address onto the RAS. */
- void push(const Addr &return_addr);
-
- /** Pops the top address from the RAS. */
- void pop();
-
- /** Changes index to the top of the RAS, and replaces the top address with
- * a new target.
- * @param top_entry_idx The index of the RAS that will now be the top.
- * @param restored_target The new target address of the new top of the RAS.
- */
- void restore(unsigned top_entry_idx, const Addr &restored_target);
-
- private:
- /** Increments the top of stack index. */
- inline void incrTos()
- { if (++tos == numEntries) tos = 0; }
-
- /** Decrements the top of stack index. */
- inline void decrTos()
- { tos = (tos == 0 ? numEntries - 1 : tos - 1); }
-
- /** The RAS itself. */
- std::vector<Addr> addrStack;
-
- /** The number of entries in the RAS. */
- unsigned numEntries;
-
- /** The number of used entries in the RAS. */
- unsigned usedEntries;
-
- /** The top of stack index. */
- unsigned tos;
-};
-
-#endif // __CPU_O3_RAS_HH__
diff --git a/cpu/o3/regfile.hh b/cpu/o3/regfile.hh
deleted file mode 100644
index ed1238d36..000000000
--- a/cpu/o3/regfile.hh
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_REGFILE_HH__
-#define __CPU_O3_REGFILE_HH__
-
-#include "arch/isa_traits.hh"
-#include "arch/faults.hh"
-#include "base/trace.hh"
-#include "config/full_system.hh"
-#include "cpu/o3/comm.hh"
-
-#if FULL_SYSTEM
-#include "kern/kernel_stats.hh"
-
-#endif
-
-#include <vector>
-
-/**
- * Simple physical register file class.
- * This really only depends on the ISA, and not the Impl. Things that are
- * in the ifdef FULL_SYSTEM are pretty dependent on the ISA, and probably
- * should go in the AlphaFullCPU.
- */
-template <class Impl>
-class PhysRegFile
-{
- protected:
- typedef TheISA::IntReg IntReg;
- typedef TheISA::FloatReg FloatReg;
- typedef TheISA::MiscRegFile MiscRegFile;
- typedef TheISA::MiscReg MiscReg;
- // Note that most of the definitions of the IntReg, FloatReg, etc. exist
- // within the Impl/ISA class and not within this PhysRegFile class.
-
- // Will make these registers public for now, but they probably should
- // be private eventually with some accessor functions.
- public:
- typedef typename Impl::FullCPU FullCPU;
-
- /**
- * Constructs a physical register file with the specified amount of
- * integer and floating point registers.
- */
- PhysRegFile(unsigned _numPhysicalIntRegs,
- unsigned _numPhysicalFloatRegs);
-
- //Everything below should be pretty well identical to the normal
- //register file that exists within AlphaISA class.
- //The duplication is unfortunate but it's better than having
- //different ways to access certain registers.
-
- //Add these in later when everything else is in place
-// void serialize(std::ostream &os);
-// void unserialize(Checkpoint *cp, const std::string &section);
-
- /** Reads an integer register. */
- uint64_t readIntReg(PhysRegIndex reg_idx)
- {
- assert(reg_idx < numPhysicalIntRegs);
-
- DPRINTF(IEW, "RegFile: Access to int register %i, has data "
- "%i\n", int(reg_idx), intRegFile[reg_idx]);
- return intRegFile[reg_idx];
- }
-
- /** Reads a floating point register (single precision). */
- float readFloatRegSingle(PhysRegIndex reg_idx)
- {
- // Remove the base Float reg dependency.
- reg_idx = reg_idx - numPhysicalIntRegs;
-
- assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
-
- DPRINTF(IEW, "RegFile: Access to float register %i as single, has "
- "data %8.8f\n", int(reg_idx), (float)floatRegFile[reg_idx].d);
-
- return (float)floatRegFile[reg_idx].d;
- }
-
- /** Reads a floating point register (double precision). */
- double readFloatRegDouble(PhysRegIndex reg_idx)
- {
- // Remove the base Float reg dependency.
- reg_idx = reg_idx - numPhysicalIntRegs;
-
- assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
-
- DPRINTF(IEW, "RegFile: Access to float register %i as double, has "
- " data %8.8f\n", int(reg_idx), floatRegFile[reg_idx].d);
-
- return floatRegFile[reg_idx].d;
- }
-
- /** Reads a floating point register as an integer. */
- uint64_t readFloatRegInt(PhysRegIndex reg_idx)
- {
- // Remove the base Float reg dependency.
- reg_idx = reg_idx - numPhysicalIntRegs;
-
- assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
-
- DPRINTF(IEW, "RegFile: Access to float register %i as int, has data "
- "%lli\n", int(reg_idx), floatRegFile[reg_idx].q);
-
- return floatRegFile[reg_idx].q;
- }
-
- /** Sets an integer register to the given value. */
- void setIntReg(PhysRegIndex reg_idx, uint64_t val)
- {
- assert(reg_idx < numPhysicalIntRegs);
-
- DPRINTF(IEW, "RegFile: Setting int register %i to %lli\n",
- int(reg_idx), val);
-
- if (reg_idx != TheISA::ZeroReg)
- intRegFile[reg_idx] = val;
- }
-
- /** Sets a single precision floating point register to the given value. */
- void setFloatRegSingle(PhysRegIndex reg_idx, float val)
- {
- // Remove the base Float reg dependency.
- reg_idx = reg_idx - numPhysicalIntRegs;
-
- assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
-
- DPRINTF(IEW, "RegFile: Setting float register %i to %8.8f\n",
- int(reg_idx), val);
-
- if (reg_idx != TheISA::ZeroReg)
- floatRegFile[reg_idx].d = (double)val;
- }
-
- /** Sets a double precision floating point register to the given value. */
- void setFloatRegDouble(PhysRegIndex reg_idx, double val)
- {
- // Remove the base Float reg dependency.
- reg_idx = reg_idx - numPhysicalIntRegs;
-
- assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
-
- DPRINTF(IEW, "RegFile: Setting float register %i to %8.8f\n",
- int(reg_idx), val);
-
- if (reg_idx != TheISA::ZeroReg)
- floatRegFile[reg_idx].d = val;
- }
-
- /** Sets a floating point register to the given integer value. */
- void setFloatRegInt(PhysRegIndex reg_idx, uint64_t val)
- {
- // Remove the base Float reg dependency.
- reg_idx = reg_idx - numPhysicalIntRegs;
-
- assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
-
- DPRINTF(IEW, "RegFile: Setting float register %i to %lli\n",
- int(reg_idx), val);
-
- if (reg_idx != TheISA::ZeroReg)
- floatRegFile[reg_idx].q = val;
- }
-
- //Consider leaving this stuff and below in some implementation specific
- //file as opposed to the general register file. Or have a derived class.
- MiscReg readMiscReg(int misc_reg, unsigned thread_id)
- {
- return miscRegs[thread_id].readReg(misc_reg);
- }
-
- MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault,
- unsigned thread_id)
- {
- return miscRegs[thread_id].readRegWithEffect(misc_reg, fault,
- cpu->xcBase(thread_id));
- }
-
- Fault setMiscReg(int misc_reg, const MiscReg &val, unsigned thread_id)
- {
- return miscRegs[thread_id].setReg(misc_reg, val);
- }
-
- Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val,
- unsigned thread_id)
- {
- return miscRegs[thread_id].setRegWithEffect(misc_reg, val,
- cpu->xcBase(thread_id));
- }
-
-#if FULL_SYSTEM
- int readIntrFlag() { return intrflag; }
- /** Sets an interrupt flag. */
- void setIntrFlag(int val) { intrflag = val; }
-#endif
-
- public:
- /** (signed) integer register file. */
- std::vector<IntReg> intRegFile;
-
- /** Floating point register file. */
- std::vector<FloatReg> floatRegFile;
-
- /** Miscellaneous register file. */
- MiscRegFile miscRegs[Impl::MaxThreads];
-
-#if FULL_SYSTEM
- private:
- int intrflag; // interrupt flag
-#endif
-
- private:
- /** CPU pointer. */
- FullCPU *cpu;
-
- public:
- /** Sets the CPU pointer. */
- void setCPU(FullCPU *cpu_ptr) { cpu = cpu_ptr; }
-
- /** Number of physical integer registers. */
- unsigned numPhysicalIntRegs;
- /** Number of physical floating point registers. */
- unsigned numPhysicalFloatRegs;
-};
-
-template <class Impl>
-PhysRegFile<Impl>::PhysRegFile(unsigned _numPhysicalIntRegs,
- unsigned _numPhysicalFloatRegs)
- : numPhysicalIntRegs(_numPhysicalIntRegs),
- numPhysicalFloatRegs(_numPhysicalFloatRegs)
-{
- intRegFile.resize(numPhysicalIntRegs);
- floatRegFile.resize(numPhysicalFloatRegs);
-
- //memset(intRegFile, 0, sizeof(*intRegFile));
- //memset(floatRegFile, 0, sizeof(*floatRegFile));
-}
-
-#endif
diff --git a/cpu/o3/rename.cc b/cpu/o3/rename.cc
deleted file mode 100644
index 4dc3bf6b2..000000000
--- a/cpu/o3/rename.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/o3/alpha_dyn_inst.hh"
-#include "cpu/o3/alpha_impl.hh"
-#include "cpu/o3/rename_impl.hh"
-
-template class DefaultRename<AlphaSimpleImpl>;
diff --git a/cpu/o3/rename.hh b/cpu/o3/rename.hh
deleted file mode 100644
index 4912431ad..000000000
--- a/cpu/o3/rename.hh
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_RENAME_HH__
-#define __CPU_O3_RENAME_HH__
-
-#include <list>
-
-#include "base/statistics.hh"
-#include "base/timebuf.hh"
-
-/**
- * DefaultRename handles both single threaded and SMT rename. Its
- * width is specified by the parameters; each cycle it tries to rename
- * that many instructions. It holds onto the rename history of all
- * instructions with destination registers, storing the
- * arch. register, the new physical register, and the old physical
- * register, to allow for undoing of mappings if squashing happens, or
- * freeing up registers upon commit. Rename handles blocking if the
- * ROB, IQ, or LSQ is going to be full. Rename also handles barriers,
- * and does so by stalling on the instruction until the ROB is empty
- * and there are no instructions in flight to the ROB.
- */
-template<class Impl>
-class DefaultRename
-{
- public:
- // Typedefs from the Impl.
- typedef typename Impl::CPUPol CPUPol;
- typedef typename Impl::DynInstPtr DynInstPtr;
- typedef typename Impl::FullCPU FullCPU;
- typedef typename Impl::Params Params;
-
- // Typedefs from the CPUPol
- typedef typename CPUPol::DecodeStruct DecodeStruct;
- typedef typename CPUPol::RenameStruct RenameStruct;
- typedef typename CPUPol::TimeStruct TimeStruct;
- typedef typename CPUPol::FreeList FreeList;
- typedef typename CPUPol::RenameMap RenameMap;
- // These are used only for initialization.
- typedef typename CPUPol::IEW IEW;
- typedef typename CPUPol::Commit Commit;
-
- // Typedefs from the ISA.
- typedef TheISA::RegIndex RegIndex;
-
- // A list is used to queue the instructions. Barrier insts must
- // be added to the front of the list, which is the only reason for
- // using a list instead of a queue. (Most other stages use a
- // queue)
- typedef std::list<DynInstPtr> InstQueue;
-
- public:
- /** Overall rename status. Used to determine if the CPU can
- * deschedule itself due to a lack of activity.
- */
- enum RenameStatus {
- Active,
- Inactive
- };
-
- /** Individual thread status. */
- enum ThreadStatus {
- Running,
- Idle,
- StartSquash,
- Squashing,
- Blocked,
- Unblocking,
- SerializeStall
- };
-
- private:
- /** Rename status. */
- RenameStatus _status;
-
- /** Per-thread status. */
- ThreadStatus renameStatus[Impl::MaxThreads];
-
- public:
- /** DefaultRename constructor. */
- DefaultRename(Params *params);
-
- /** Returns the name of rename. */
- std::string name() const;
-
- /** Registers statistics. */
- void regStats();
-
- /** Sets CPU pointer. */
- void setCPU(FullCPU *cpu_ptr);
-
- /** Sets the main backwards communication time buffer pointer. */
- void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
-
- /** Sets pointer to time buffer used to communicate to the next stage. */
- void setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr);
-
- /** Sets pointer to time buffer coming from decode. */
- void setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr);
-
- /** Sets pointer to IEW stage. Used only for initialization. */
- void setIEWStage(IEW *iew_stage)
- { iew_ptr = iew_stage; }
-
- /** Sets pointer to commit stage. Used only for initialization. */
- void setCommitStage(Commit *commit_stage)
- { commit_ptr = commit_stage; }
-
- private:
- /** Pointer to IEW stage. Used only for initialization. */
- IEW *iew_ptr;
-
- /** Pointer to commit stage. Used only for initialization. */
- Commit *commit_ptr;
-
- public:
- /** Initializes variables for the stage. */
- void initStage();
-
- /** Sets pointer to list of active threads. */
- void setActiveThreads(std::list<unsigned> *at_ptr);
-
- /** Sets pointer to rename maps (per-thread structures). */
- void setRenameMap(RenameMap rm_ptr[Impl::MaxThreads]);
-
- /** Sets pointer to the free list. */
- void setFreeList(FreeList *fl_ptr);
-
- /** Sets pointer to the scoreboard. */
- void setScoreboard(Scoreboard *_scoreboard);
-
- /** Switches out the rename stage. */
- void switchOut();
-
- /** Completes the switch out. */
- void doSwitchOut();
-
- /** Takes over from another CPU's thread. */
- void takeOverFrom();
-
- /** Squashes all instructions in a thread. */
- void squash(unsigned tid);
-
- /** Ticks rename, which processes all input signals and attempts to rename
- * as many instructions as possible.
- */
- void tick();
-
- /** Debugging function used to dump history buffer of renamings. */
- void dumpHistory();
-
- private:
- /** Determines what to do based on rename's current status.
- * @param status_change rename() sets this variable if there was a status
- * change (ie switching from blocking to unblocking).
- * @param tid Thread id to rename instructions from.
- */
- void rename(bool &status_change, unsigned tid);
-
- /** Renames instructions for the given thread. Also handles serializing
- * instructions.
- */
- void renameInsts(unsigned tid);
-
- /** Inserts unused instructions from a given thread into the skid buffer,
- * to be renamed once rename unblocks.
- */
- void skidInsert(unsigned tid);
-
- /** Separates instructions from decode into individual lists of instructions
- * sorted by thread.
- */
- void sortInsts();
-
- /** Returns if all of the skid buffers are empty. */
- bool skidsEmpty();
-
- /** Updates overall rename status based on all of the threads' statuses. */
- void updateStatus();
-
- /** Switches rename to blocking, and signals back that rename has become
- * blocked.
- * @return Returns true if there is a status change.
- */
- bool block(unsigned tid);
-
- /** Switches rename to unblocking if the skid buffer is empty, and signals
- * back that rename has unblocked.
- * @return Returns true if there is a status change.
- */
- bool unblock(unsigned tid);
-
- /** Executes actual squash, removing squashed instructions. */
- void doSquash(unsigned tid);
-
- /** Removes a committed instruction's rename history. */
- void removeFromHistory(InstSeqNum inst_seq_num, unsigned tid);
-
- /** Renames the source registers of an instruction. */
- inline void renameSrcRegs(DynInstPtr &inst, unsigned tid);
-
- /** Renames the destination registers of an instruction. */
- inline void renameDestRegs(DynInstPtr &inst, unsigned tid);
-
- /** Calculates the number of free ROB entries for a specific thread. */
- inline int calcFreeROBEntries(unsigned tid);
-
- /** Calculates the number of free IQ entries for a specific thread. */
- inline int calcFreeIQEntries(unsigned tid);
-
- /** Calculates the number of free LSQ entries for a specific thread. */
- inline int calcFreeLSQEntries(unsigned tid);
-
- /** Returns the number of valid instructions coming from decode. */
- unsigned validInsts();
-
- /** Reads signals telling rename to block/unblock. */
- void readStallSignals(unsigned tid);
-
- /** Checks if any stages are telling rename to block. */
- bool checkStall(unsigned tid);
-
- /** Gets the number of free entries for a specific thread. */
- void readFreeEntries(unsigned tid);
-
- /** Checks the signals and updates the status. */
- bool checkSignalsAndUpdate(unsigned tid);
-
- /** Either serializes on the next instruction available in the InstQueue,
- * or records that it must serialize on the next instruction to enter
- * rename.
- * @param inst_list The list of younger, unprocessed instructions for the
- * thread that has the serializeAfter instruction.
- * @param tid The thread id.
- */
- void serializeAfter(InstQueue &inst_list, unsigned tid);
-
- /** Holds the information for each destination register rename. It holds
- * the instruction's sequence number, the arch register, the old physical
- * register for that arch. register, and the new physical register.
- */
- struct RenameHistory {
- RenameHistory(InstSeqNum _instSeqNum, RegIndex _archReg,
- PhysRegIndex _newPhysReg, PhysRegIndex _prevPhysReg)
- : instSeqNum(_instSeqNum), archReg(_archReg),
- newPhysReg(_newPhysReg), prevPhysReg(_prevPhysReg)
- {
- }
-
- /** The sequence number of the instruction that renamed. */
- InstSeqNum instSeqNum;
- /** The architectural register index that was renamed. */
- RegIndex archReg;
- /** The new physical register that the arch. register is renamed to. */
- PhysRegIndex newPhysReg;
- /** The old physical register that the arch. register was renamed to. */
- PhysRegIndex prevPhysReg;
- };
-
- /** A per-thread list of all destination register renames, used to either
- * undo rename mappings or free old physical registers.
- */
- std::list<RenameHistory> historyBuffer[Impl::MaxThreads];
-
- /** Pointer to CPU. */
- FullCPU *cpu;
-
- /** Pointer to main time buffer used for backwards communication. */
- TimeBuffer<TimeStruct> *timeBuffer;
-
- /** Wire to get IEW's output from backwards time buffer. */
- typename TimeBuffer<TimeStruct>::wire fromIEW;
-
- /** Wire to get commit's output from backwards time buffer. */
- typename TimeBuffer<TimeStruct>::wire fromCommit;
-
- /** Wire to write infromation heading to previous stages. */
- typename TimeBuffer<TimeStruct>::wire toDecode;
-
- /** Rename instruction queue. */
- TimeBuffer<RenameStruct> *renameQueue;
-
- /** Wire to write any information heading to IEW. */
- typename TimeBuffer<RenameStruct>::wire toIEW;
-
- /** Decode instruction queue interface. */
- TimeBuffer<DecodeStruct> *decodeQueue;
-
- /** Wire to get decode's output from decode queue. */
- typename TimeBuffer<DecodeStruct>::wire fromDecode;
-
- /** Queue of all instructions coming from decode this cycle. */
- InstQueue insts[Impl::MaxThreads];
-
- /** Skid buffer between rename and decode. */
- InstQueue skidBuffer[Impl::MaxThreads];
-
- /** Rename map interface. */
- RenameMap *renameMap[Impl::MaxThreads];
-
- /** Free list interface. */
- FreeList *freeList;
-
- /** Pointer to the list of active threads. */
- std::list<unsigned> *activeThreads;
-
- /** Pointer to the scoreboard. */
- Scoreboard *scoreboard;
-
- /** Count of instructions in progress that have been sent off to the IQ
- * and ROB, but are not yet included in their occupancy counts.
- */
- int instsInProgress[Impl::MaxThreads];
-
- /** Variable that tracks if decode has written to the time buffer this
- * cycle. Used to tell CPU if there is activity this cycle.
- */
- bool wroteToTimeBuffer;
-
- /** Structures whose free entries impact the amount of instructions that
- * can be renamed.
- */
- struct FreeEntries {
- unsigned iqEntries;
- unsigned lsqEntries;
- unsigned robEntries;
- };
-
- /** Per-thread tracking of the number of free entries of back-end
- * structures.
- */
- FreeEntries freeEntries[Impl::MaxThreads];
-
- /** Records if the ROB is empty. In SMT mode the ROB may be dynamically
- * partitioned between threads, so the ROB must tell rename when it is
- * empty.
- */
- bool emptyROB[Impl::MaxThreads];
-
- /** Source of possible stalls. */
- struct Stalls {
- bool iew;
- bool commit;
- };
-
- /** Tracks which stages are telling decode to stall. */
- Stalls stalls[Impl::MaxThreads];
-
- /** The serialize instruction that rename has stalled on. */
- DynInstPtr serializeInst[Impl::MaxThreads];
-
- /** Records if rename needs to serialize on the next instruction for any
- * thread.
- */
- bool serializeOnNextInst[Impl::MaxThreads];
-
- /** Delay between iew and rename, in ticks. */
- int iewToRenameDelay;
-
- /** Delay between decode and rename, in ticks. */
- int decodeToRenameDelay;
-
- /** Delay between commit and rename, in ticks. */
- unsigned commitToRenameDelay;
-
- /** Rename width, in instructions. */
- unsigned renameWidth;
-
- /** Commit width, in instructions. Used so rename knows how many
- * instructions might have freed registers in the previous cycle.
- */
- unsigned commitWidth;
-
- /** The index of the instruction in the time buffer to IEW that rename is
- * currently using.
- */
- unsigned toIEWIndex;
-
- /** Whether or not rename needs to block this cycle. */
- bool blockThisCycle;
-
- /** The number of threads active in rename. */
- unsigned numThreads;
-
- /** The maximum skid buffer size. */
- unsigned skidBufferMax;
-
- /** Enum to record the source of a structure full stall. Can come from
- * either ROB, IQ, LSQ, and it is priortized in that order.
- */
- enum FullSource {
- ROB,
- IQ,
- LSQ,
- NONE
- };
-
- /** Function used to increment the stat that corresponds to the source of
- * the stall.
- */
- inline void incrFullStat(const FullSource &source);
-
- /** Stat for total number of cycles spent squashing. */
- Stats::Scalar<> renameSquashCycles;
- /** Stat for total number of cycles spent idle. */
- Stats::Scalar<> renameIdleCycles;
- /** Stat for total number of cycles spent blocking. */
- Stats::Scalar<> renameBlockCycles;
- /** Stat for total number of cycles spent stalling for a serializing inst. */
- Stats::Scalar<> renameSerializeStallCycles;
- /** Stat for total number of cycles spent running normally. */
- Stats::Scalar<> renameRunCycles;
- /** Stat for total number of cycles spent unblocking. */
- Stats::Scalar<> renameUnblockCycles;
- /** Stat for total number of renamed instructions. */
- Stats::Scalar<> renameRenamedInsts;
- /** Stat for total number of squashed instructions that rename discards. */
- Stats::Scalar<> renameSquashedInsts;
- /** Stat for total number of times that the ROB starts a stall in rename. */
- Stats::Scalar<> renameROBFullEvents;
- /** Stat for total number of times that the IQ starts a stall in rename. */
- Stats::Scalar<> renameIQFullEvents;
- /** Stat for total number of times that the LSQ starts a stall in rename. */
- Stats::Scalar<> renameLSQFullEvents;
- /** Stat for total number of times that rename runs out of free registers
- * to use to rename. */
- Stats::Scalar<> renameFullRegistersEvents;
- /** Stat for total number of renamed destination registers. */
- Stats::Scalar<> renameRenamedOperands;
- /** Stat for total number of source register rename lookups. */
- Stats::Scalar<> renameRenameLookups;
- /** Stat for total number of committed renaming mappings. */
- Stats::Scalar<> renameCommittedMaps;
- /** Stat for total number of mappings that were undone due to a squash. */
- Stats::Scalar<> renameUndoneMaps;
- /** Number of serialize instructions handled. */
- Stats::Scalar<> renamedSerializing;
- /** Number of instructions marked as temporarily serializing. */
- Stats::Scalar<> renamedTempSerializing;
- /** Number of instructions inserted into skid buffers. */
- Stats::Scalar<> renameSkidInsts;
-};
-
-#endif // __CPU_O3_RENAME_HH__
diff --git a/cpu/o3/rename_impl.hh b/cpu/o3/rename_impl.hh
deleted file mode 100644
index 829c99584..000000000
--- a/cpu/o3/rename_impl.hh
+++ /dev/null
@@ -1,1281 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <list>
-
-#include "config/full_system.hh"
-#include "cpu/o3/rename.hh"
-
-using namespace std;
-
-template <class Impl>
-DefaultRename<Impl>::DefaultRename(Params *params)
- : iewToRenameDelay(params->iewToRenameDelay),
- decodeToRenameDelay(params->decodeToRenameDelay),
- commitToRenameDelay(params->commitToRenameDelay),
- renameWidth(params->renameWidth),
- commitWidth(params->commitWidth),
- numThreads(params->numberOfThreads)
-{
- _status = Inactive;
-
- for (int i=0; i< numThreads; i++) {
- renameStatus[i] = Idle;
-
- freeEntries[i].iqEntries = 0;
- freeEntries[i].lsqEntries = 0;
- freeEntries[i].robEntries = 0;
-
- stalls[i].iew = false;
- stalls[i].commit = false;
- serializeInst[i] = NULL;
-
- instsInProgress[i] = 0;
-
- emptyROB[i] = true;
-
- serializeOnNextInst[i] = false;
- }
-
- // @todo: Make into a parameter.
- skidBufferMax = (2 * (iewToRenameDelay * params->decodeWidth)) + renameWidth;
-}
-
-template <class Impl>
-std::string
-DefaultRename<Impl>::name() const
-{
- return cpu->name() + ".rename";
-}
-
-template <class Impl>
-void
-DefaultRename<Impl>::regStats()
-{
- renameSquashCycles
- .name(name() + ".RENAME:SquashCycles")
- .desc("Number of cycles rename is squashing")
- .prereq(renameSquashCycles);
- renameIdleCycles
- .name(name() + ".RENAME:IdleCycles")
- .desc("Number of cycles rename is idle")
- .prereq(renameIdleCycles);
- renameBlockCycles
- .name(name() + ".RENAME:BlockCycles")
- .desc("Number of cycles rename is blocking")
- .prereq(renameBlockCycles);
- renameSerializeStallCycles
- .name(name() + ".RENAME:serializeStallCycles")
- .desc("count of cycles rename stalled for serializing inst")
- .flags(Stats::total);
- renameRunCycles
- .name(name() + ".RENAME:RunCycles")
- .desc("Number of cycles rename is running")
- .prereq(renameIdleCycles);
- renameUnblockCycles
- .name(name() + ".RENAME:UnblockCycles")
- .desc("Number of cycles rename is unblocking")
- .prereq(renameUnblockCycles);
- renameRenamedInsts
- .name(name() + ".RENAME:RenamedInsts")
- .desc("Number of instructions processed by rename")
- .prereq(renameRenamedInsts);
- renameSquashedInsts
- .name(name() + ".RENAME:SquashedInsts")
- .desc("Number of squashed instructions processed by rename")
- .prereq(renameSquashedInsts);
- renameROBFullEvents
- .name(name() + ".RENAME:ROBFullEvents")
- .desc("Number of times rename has blocked due to ROB full")
- .prereq(renameROBFullEvents);
- renameIQFullEvents
- .name(name() + ".RENAME:IQFullEvents")
- .desc("Number of times rename has blocked due to IQ full")
- .prereq(renameIQFullEvents);
- renameLSQFullEvents
- .name(name() + ".RENAME:LSQFullEvents")
- .desc("Number of times rename has blocked due to LSQ full")
- .prereq(renameLSQFullEvents);
- renameFullRegistersEvents
- .name(name() + ".RENAME:FullRegisterEvents")
- .desc("Number of times there has been no free registers")
- .prereq(renameFullRegistersEvents);
- renameRenamedOperands
- .name(name() + ".RENAME:RenamedOperands")
- .desc("Number of destination operands rename has renamed")
- .prereq(renameRenamedOperands);
- renameRenameLookups
- .name(name() + ".RENAME:RenameLookups")
- .desc("Number of register rename lookups that rename has made")
- .prereq(renameRenameLookups);
- renameCommittedMaps
- .name(name() + ".RENAME:CommittedMaps")
- .desc("Number of HB maps that are committed")
- .prereq(renameCommittedMaps);
- renameUndoneMaps
- .name(name() + ".RENAME:UndoneMaps")
- .desc("Number of HB maps that are undone due to squashing")
- .prereq(renameUndoneMaps);
- renamedSerializing
- .name(name() + ".RENAME:serializingInsts")
- .desc("count of serializing insts renamed")
- .flags(Stats::total)
- ;
- renamedTempSerializing
- .name(name() + ".RENAME:tempSerializingInsts")
- .desc("count of temporary serializing insts renamed")
- .flags(Stats::total)
- ;
- renameSkidInsts
- .name(name() + ".RENAME:skidInsts")
- .desc("count of insts added to the skid buffer")
- .flags(Stats::total)
- ;
-}
-
-template <class Impl>
-void
-DefaultRename<Impl>::setCPU(FullCPU *cpu_ptr)
-{
- DPRINTF(Rename, "Setting CPU pointer.\n");
- cpu = cpu_ptr;
-}
-
-template <class Impl>
-void
-DefaultRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
-{
- DPRINTF(Rename, "Setting time buffer pointer.\n");
- timeBuffer = tb_ptr;
-
- // Setup wire to read information from time buffer, from IEW stage.
- fromIEW = timeBuffer->getWire(-iewToRenameDelay);
-
- // Setup wire to read infromation from time buffer, from commit stage.
- fromCommit = timeBuffer->getWire(-commitToRenameDelay);
-
- // Setup wire to write information to previous stages.
- toDecode = timeBuffer->getWire(0);
-}
-
-template <class Impl>
-void
-DefaultRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
-{
- DPRINTF(Rename, "Setting rename queue pointer.\n");
- renameQueue = rq_ptr;
-
- // Setup wire to write information to future stages.
- toIEW = renameQueue->getWire(0);
-}
-
-template <class Impl>
-void
-DefaultRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
-{
- DPRINTF(Rename, "Setting decode queue pointer.\n");
- decodeQueue = dq_ptr;
-
- // Setup wire to get information from decode.
- fromDecode = decodeQueue->getWire(-decodeToRenameDelay);
-}
-
-template <class Impl>
-void
-DefaultRename<Impl>::initStage()
-{
- // Grab the number of free entries directly from the stages.
- for (int tid=0; tid < numThreads; tid++) {
- freeEntries[tid].iqEntries = iew_ptr->instQueue.numFreeEntries(tid);
- freeEntries[tid].lsqEntries = iew_ptr->ldstQueue.numFreeEntries(tid);
- freeEntries[tid].robEntries = commit_ptr->numROBFreeEntries(tid);
- emptyROB[tid] = true;
- }
-}
-
-template<class Impl>
-void
-DefaultRename<Impl>::setActiveThreads(list<unsigned> *at_ptr)
-{
- DPRINTF(Rename, "Setting active threads list pointer.\n");
- activeThreads = at_ptr;
-}
-
-
-template <class Impl>
-void
-DefaultRename<Impl>::setRenameMap(RenameMap rm_ptr[])
-{
- DPRINTF(Rename, "Setting rename map pointers.\n");
-
- for (int i=0; i<numThreads; i++) {
- renameMap[i] = &rm_ptr[i];
- }
-}
-
-template <class Impl>
-void
-DefaultRename<Impl>::setFreeList(FreeList *fl_ptr)
-{
- DPRINTF(Rename, "Setting free list pointer.\n");
- freeList = fl_ptr;
-}
-
-template<class Impl>
-void
-DefaultRename<Impl>::setScoreboard(Scoreboard *_scoreboard)
-{
- DPRINTF(Rename, "Setting scoreboard pointer.\n");
- scoreboard = _scoreboard;
-}
-
-template <class Impl>
-void
-DefaultRename<Impl>::switchOut()
-{
- // Rename is ready to switch out at any time.
- cpu->signalSwitched();
-}
-
-template <class Impl>
-void
-DefaultRename<Impl>::doSwitchOut()
-{
- // Clear any state, fix up the rename map.
- for (int i = 0; i < numThreads; i++) {
- typename list<RenameHistory>::iterator hb_it = historyBuffer[i].begin();
-
- while (!historyBuffer[i].empty()) {
- assert(hb_it != historyBuffer[i].end());
-
- DPRINTF(Rename, "[tid:%u]: Removing history entry with sequence "
- "number %i.\n", i, (*hb_it).instSeqNum);
-
- // Tell the rename map to set the architected register to the
- // previous physical register that it was renamed to.
- renameMap[i]->setEntry(hb_it->archReg, hb_it->prevPhysReg);
-
- // Put the renamed physical register back on the free list.
- freeList->addReg(hb_it->newPhysReg);
-
- historyBuffer[i].erase(hb_it++);
- }
- insts[i].clear();
- skidBuffer[i].clear();
- }
-}
-
-template <class Impl>
-void
-DefaultRename<Impl>::takeOverFrom()
-{
- _status = Inactive;
- initStage();
-
- // Reset all state prior to taking over from the other CPU.
- for (int i=0; i< numThreads; i++) {
- renameStatus[i] = Idle;
-
- stalls[i].iew = false;
- stalls[i].commit = false;
- serializeInst[i] = NULL;
-
- instsInProgress[i] = 0;
-
- emptyROB[i] = true;
-
- serializeOnNextInst[i] = false;
- }
-}
-
-template <class Impl>
-void
-DefaultRename<Impl>::squash(unsigned tid)
-{
- DPRINTF(Rename, "[tid:%u]: Squashing instructions.\n",tid);
-
- // Clear the stall signal if rename was blocked or unblocking before.
- // If it still needs to block, the blocking should happen the next
- // cycle and there should be space to hold everything due to the squash.
- if (renameStatus[tid] == Blocked ||
- renameStatus[tid] == Unblocking ||
- renameStatus[tid] == SerializeStall) {
-#if 0
- // In syscall emulation, we can have both a block and a squash due
- // to a syscall in the same cycle. This would cause both signals to
- // be high. This shouldn't happen in full system.
- if (toDecode->renameBlock[tid]) {
- toDecode->renameBlock[tid] = 0;
- } else {
- toDecode->renameUnblock[tid] = 1;
- }
-#else
- toDecode->renameUnblock[tid] = 1;
-#endif
- serializeInst[tid] = NULL;
- }
-
- // Set the status to Squashing.
- renameStatus[tid] = Squashing;
-
- // Squash any instructions from decode.
- unsigned squashCount = 0;
-
- for (int i=0; i<fromDecode->size; i++) {
- if (fromDecode->insts[i]->threadNumber == tid) {
- fromDecode->insts[i]->squashed = true;
- wroteToTimeBuffer = true;
- squashCount++;
- }
- }
-
- insts[tid].clear();
-
- // Clear the skid buffer in case it has any data in it.
- skidBuffer[tid].clear();
-
- doSquash(tid);
-}
-
-template <class Impl>
-void
-DefaultRename<Impl>::tick()
-{
- wroteToTimeBuffer = false;
-
- blockThisCycle = false;
-
- bool status_change = false;
-
- toIEWIndex = 0;
-
- sortInsts();
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- // Check stall and squash signals.
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- DPRINTF(Rename, "Processing [tid:%i]\n", tid);
-
- status_change = checkSignalsAndUpdate(tid) || status_change;
-
- rename(status_change, tid);
- }
-
- if (status_change) {
- updateStatus();
- }
-
- if (wroteToTimeBuffer) {
- DPRINTF(Activity, "Activity this cycle.\n");
- cpu->activityThisCycle();
- }
-
- threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- // If we committed this cycle then doneSeqNum will be > 0
- if (fromCommit->commitInfo[tid].doneSeqNum != 0 &&
- !fromCommit->commitInfo[tid].squash &&
- renameStatus[tid] != Squashing) {
-
- removeFromHistory(fromCommit->commitInfo[tid].doneSeqNum,
- tid);
- }
- }
-
- // @todo: make into updateProgress function
- for (int tid=0; tid < numThreads; tid++) {
- instsInProgress[tid] -= fromIEW->iewInfo[tid].dispatched;
-
- assert(instsInProgress[tid] >=0);
- }
-
-}
-
-template<class Impl>
-void
-DefaultRename<Impl>::rename(bool &status_change, unsigned tid)
-{
- // If status is Running or idle,
- // call renameInsts()
- // If status is Unblocking,
- // buffer any instructions coming from decode
- // continue trying to empty skid buffer
- // check if stall conditions have passed
-
- if (renameStatus[tid] == Blocked) {
- ++renameBlockCycles;
- } else if (renameStatus[tid] == Squashing) {
- ++renameSquashCycles;
- } else if (renameStatus[tid] == SerializeStall) {
- ++renameSerializeStallCycles;
- }
-
- if (renameStatus[tid] == Running ||
- renameStatus[tid] == Idle) {
- DPRINTF(Rename, "[tid:%u]: Not blocked, so attempting to run "
- "stage.\n", tid);
-
- renameInsts(tid);
- } else if (renameStatus[tid] == Unblocking) {
- renameInsts(tid);
-
- if (validInsts()) {
- // Add the current inputs to the skid buffer so they can be
- // reprocessed when this stage unblocks.
- skidInsert(tid);
- }
-
- // If we switched over to blocking, then there's a potential for
- // an overall status change.
- status_change = unblock(tid) || status_change || blockThisCycle;
- }
-}
-
-template <class Impl>
-void
-DefaultRename<Impl>::renameInsts(unsigned tid)
-{
- // Instructions can be either in the skid buffer or the queue of
- // instructions coming from decode, depending on the status.
- int insts_available = renameStatus[tid] == Unblocking ?
- skidBuffer[tid].size() : insts[tid].size();
-
- // Check the decode queue to see if instructions are available.
- // If there are no available instructions to rename, then do nothing.
- if (insts_available == 0) {
- DPRINTF(Rename, "[tid:%u]: Nothing to do, breaking out early.\n",
- tid);
- // Should I change status to idle?
- ++renameIdleCycles;
- return;
- } else if (renameStatus[tid] == Unblocking) {
- ++renameUnblockCycles;
- } else if (renameStatus[tid] == Running) {
- ++renameRunCycles;
- }
-
- DynInstPtr inst;
-
- // Will have to do a different calculation for the number of free
- // entries.
- int free_rob_entries = calcFreeROBEntries(tid);
- int free_iq_entries = calcFreeIQEntries(tid);
- int free_lsq_entries = calcFreeLSQEntries(tid);
- int min_free_entries = free_rob_entries;
-
- FullSource source = ROB;
-
- if (free_iq_entries < min_free_entries) {
- min_free_entries = free_iq_entries;
- source = IQ;
- }
-
- if (free_lsq_entries < min_free_entries) {
- min_free_entries = free_lsq_entries;
- source = LSQ;
- }
-
- // Check if there's any space left.
- if (min_free_entries <= 0) {
- DPRINTF(Rename, "[tid:%u]: Blocking due to no free ROB/IQ/LSQ "
- "entries.\n"
- "ROB has %i free entries.\n"
- "IQ has %i free entries.\n"
- "LSQ has %i free entries.\n",
- tid,
- free_rob_entries,
- free_iq_entries,
- free_lsq_entries);
-
- blockThisCycle = true;
-
- block(tid);
-
- incrFullStat(source);
-
- return;
- } else if (min_free_entries < insts_available) {
- DPRINTF(Rename, "[tid:%u]: Will have to block this cycle."
- "%i insts available, but only %i insts can be "
- "renamed due to ROB/IQ/LSQ limits.\n",
- tid, insts_available, min_free_entries);
-
- insts_available = min_free_entries;
-
- blockThisCycle = true;
-
- incrFullStat(source);
- }
-
- InstQueue &insts_to_rename = renameStatus[tid] == Unblocking ?
- skidBuffer[tid] : insts[tid];
-
- DPRINTF(Rename, "[tid:%u]: %i available instructions to "
- "send iew.\n", tid, insts_available);
-
- DPRINTF(Rename, "[tid:%u]: %i insts pipelining from Rename | %i insts "
- "dispatched to IQ last cycle.\n",
- tid, instsInProgress[tid], fromIEW->iewInfo[tid].dispatched);
-
- // Handle serializing the next instruction if necessary.
- if (serializeOnNextInst[tid]) {
- if (emptyROB[tid] && instsInProgress[tid] == 0) {
- // ROB already empty; no need to serialize.
- serializeOnNextInst[tid] = false;
- } else if (!insts_to_rename.empty()) {
- insts_to_rename.front()->setSerializeBefore();
- }
- }
-
- int renamed_insts = 0;
-
- while (insts_available > 0 && toIEWIndex < renameWidth) {
- DPRINTF(Rename, "[tid:%u]: Sending instructions to IEW.\n", tid);
-
- assert(!insts_to_rename.empty());
-
- inst = insts_to_rename.front();
-
- insts_to_rename.pop_front();
-
- if (renameStatus[tid] == Unblocking) {
- DPRINTF(Rename,"[tid:%u]: Removing [sn:%lli] PC:%#x from rename "
- "skidBuffer\n",
- tid, inst->seqNum, inst->readPC());
- }
-
- if (inst->isSquashed()) {
- DPRINTF(Rename, "[tid:%u]: instruction %i with PC %#x is "
- "squashed, skipping.\n",
- tid, inst->seqNum, inst->threadNumber,inst->readPC());
-
- ++renameSquashedInsts;
-
- // Decrement how many instructions are available.
- --insts_available;
-
- continue;
- }
-
- DPRINTF(Rename, "[tid:%u]: Processing instruction [sn:%lli] with "
- "PC %#x.\n",
- tid, inst->seqNum, inst->readPC());
-
- // Handle serializeAfter/serializeBefore instructions.
- // serializeAfter marks the next instruction as serializeBefore.
- // serializeBefore makes the instruction wait in rename until the ROB
- // is empty.
-
- // In this model, IPR accesses are serialize before
- // instructions, and store conditionals are serialize after
- // instructions. This is mainly due to lack of support for
- // out-of-order operations of either of those classes of
- // instructions.
- if ((inst->isIprAccess() || inst->isSerializeBefore()) &&
- !inst->isSerializeHandled()) {
- DPRINTF(Rename, "Serialize before instruction encountered.\n");
-
- if (!inst->isTempSerializeBefore()) {
- renamedSerializing++;
- inst->setSerializeHandled();
- } else {
- renamedTempSerializing++;
- }
-
- // Change status over to SerializeStall so that other stages know
- // what this is blocked on.
- renameStatus[tid] = SerializeStall;
-
- serializeInst[tid] = inst;
-
- blockThisCycle = true;
-
- break;
- } else if ((inst->isStoreConditional() || inst->isSerializeAfter()) &&
- !inst->isSerializeHandled()) {
- DPRINTF(Rename, "Serialize after instruction encountered.\n");
-
- renamedSerializing++;
-
- inst->setSerializeHandled();
-
- serializeAfter(insts_to_rename, tid);
- }
-
- // Check here to make sure there are enough destination registers
- // to rename to. Otherwise block.
- if (renameMap[tid]->numFreeEntries() < inst->numDestRegs()) {
- DPRINTF(Rename, "Blocking due to lack of free "
- "physical registers to rename to.\n");
- blockThisCycle = true;
-
- ++renameFullRegistersEvents;
-
- break;
- }
-
- renameSrcRegs(inst, inst->threadNumber);
-
- renameDestRegs(inst, inst->threadNumber);
-
- ++renamed_insts;
-
- // Put instruction in rename queue.
- toIEW->insts[toIEWIndex] = inst;
- ++(toIEW->size);
-
- // Increment which instruction we're on.
- ++toIEWIndex;
-
- // Decrement how many instructions are available.
- --insts_available;
- }
-
- instsInProgress[tid] += renamed_insts;
- renameRenamedInsts += renamed_insts;
-
- // If we wrote to the time buffer, record this.
- if (toIEWIndex) {
- wroteToTimeBuffer = true;
- }
-
- // Check if there's any instructions left that haven't yet been renamed.
- // If so then block.
- if (insts_available) {
- blockThisCycle = true;
- }
-
- if (blockThisCycle) {
- block(tid);
- toDecode->renameUnblock[tid] = false;
- }
-}
-
-template<class Impl>
-void
-DefaultRename<Impl>::skidInsert(unsigned tid)
-{
- DynInstPtr inst = NULL;
-
- while (!insts[tid].empty()) {
- inst = insts[tid].front();
-
- insts[tid].pop_front();
-
- assert(tid == inst->threadNumber);
-
- DPRINTF(Rename, "[tid:%u]: Inserting [sn:%lli] PC:%#x into Rename "
- "skidBuffer\n", tid, inst->seqNum, inst->readPC());
-
- ++renameSkidInsts;
-
- skidBuffer[tid].push_back(inst);
- }
-
- if (skidBuffer[tid].size() > skidBufferMax)
- panic("Skidbuffer Exceeded Max Size");
-}
-
-template <class Impl>
-void
-DefaultRename<Impl>::sortInsts()
-{
- int insts_from_decode = fromDecode->size;
-#ifdef DEBUG
- for (int i=0; i < numThreads; i++)
- assert(insts[i].empty());
-#endif
- for (int i = 0; i < insts_from_decode; ++i) {
- DynInstPtr inst = fromDecode->insts[i];
- insts[inst->threadNumber].push_back(inst);
- }
-}
-
-template<class Impl>
-bool
-DefaultRename<Impl>::skidsEmpty()
-{
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- if (!skidBuffer[*threads++].empty())
- return false;
- }
-
- return true;
-}
-
-template<class Impl>
-void
-DefaultRename<Impl>::updateStatus()
-{
- bool any_unblocking = false;
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- if (renameStatus[tid] == Unblocking) {
- any_unblocking = true;
- break;
- }
- }
-
- // Rename will have activity if it's unblocking.
- if (any_unblocking) {
- if (_status == Inactive) {
- _status = Active;
-
- DPRINTF(Activity, "Activating stage.\n");
-
- cpu->activateStage(FullCPU::RenameIdx);
- }
- } else {
- // If it's not unblocking, then rename will not have any internal
- // activity. Switch it to inactive.
- if (_status == Active) {
- _status = Inactive;
- DPRINTF(Activity, "Deactivating stage.\n");
-
- cpu->deactivateStage(FullCPU::RenameIdx);
- }
- }
-}
-
-template <class Impl>
-bool
-DefaultRename<Impl>::block(unsigned tid)
-{
- DPRINTF(Rename, "[tid:%u]: Blocking.\n", tid);
-
- // Add the current inputs onto the skid buffer, so they can be
- // reprocessed when this stage unblocks.
- skidInsert(tid);
-
- // Only signal backwards to block if the previous stages do not think
- // rename is already blocked.
- if (renameStatus[tid] != Blocked) {
- if (renameStatus[tid] != Unblocking) {
- toDecode->renameBlock[tid] = true;
- toDecode->renameUnblock[tid] = false;
- wroteToTimeBuffer = true;
- }
-
- // Rename can not go from SerializeStall to Blocked, otherwise
- // it would not know to complete the serialize stall.
- if (renameStatus[tid] != SerializeStall) {
- // Set status to Blocked.
- renameStatus[tid] = Blocked;
- return true;
- }
- }
-
- return false;
-}
-
-template <class Impl>
-bool
-DefaultRename<Impl>::unblock(unsigned tid)
-{
- DPRINTF(Rename, "[tid:%u]: Trying to unblock.\n", tid);
-
- // Rename is done unblocking if the skid buffer is empty.
- if (skidBuffer[tid].empty() && renameStatus[tid] != SerializeStall) {
-
- DPRINTF(Rename, "[tid:%u]: Done unblocking.\n", tid);
-
- toDecode->renameUnblock[tid] = true;
- wroteToTimeBuffer = true;
-
- renameStatus[tid] = Running;
- return true;
- }
-
- return false;
-}
-
-template <class Impl>
-void
-DefaultRename<Impl>::doSquash(unsigned tid)
-{
- typename list<RenameHistory>::iterator hb_it = historyBuffer[tid].begin();
-
- InstSeqNum squashed_seq_num = fromCommit->commitInfo[tid].doneSeqNum;
-
- // After a syscall squashes everything, the history buffer may be empty
- // but the ROB may still be squashing instructions.
- if (historyBuffer[tid].empty()) {
- return;
- }
-
- // Go through the most recent instructions, undoing the mappings
- // they did and freeing up the registers.
- while (!historyBuffer[tid].empty() &&
- (*hb_it).instSeqNum > squashed_seq_num) {
- assert(hb_it != historyBuffer[tid].end());
-
- DPRINTF(Rename, "[tid:%u]: Removing history entry with sequence "
- "number %i.\n", tid, (*hb_it).instSeqNum);
-
- // Tell the rename map to set the architected register to the
- // previous physical register that it was renamed to.
- renameMap[tid]->setEntry(hb_it->archReg, hb_it->prevPhysReg);
-
- // Put the renamed physical register back on the free list.
- freeList->addReg(hb_it->newPhysReg);
-
- historyBuffer[tid].erase(hb_it++);
-
- ++renameUndoneMaps;
- }
-}
-
-template<class Impl>
-void
-DefaultRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num, unsigned tid)
-{
- DPRINTF(Rename, "[tid:%u]: Removing a committed instruction from the "
- "history buffer %u (size=%i), until [sn:%lli].\n",
- tid, tid, historyBuffer[tid].size(), inst_seq_num);
-
- typename list<RenameHistory>::iterator hb_it = historyBuffer[tid].end();
-
- --hb_it;
-
- if (historyBuffer[tid].empty()) {
- DPRINTF(Rename, "[tid:%u]: History buffer is empty.\n", tid);
- return;
- } else if (hb_it->instSeqNum > inst_seq_num) {
- DPRINTF(Rename, "[tid:%u]: Old sequence number encountered. Ensure "
- "that a syscall happened recently.\n", tid);
- return;
- }
-
- // Commit all the renames up until (and including) the committed sequence
- // number. Some or even all of the committed instructions may not have
- // rename histories if they did not have destination registers that were
- // renamed.
- while (!historyBuffer[tid].empty() &&
- hb_it != historyBuffer[tid].end() &&
- (*hb_it).instSeqNum <= inst_seq_num) {
-
- DPRINTF(Rename, "[tid:%u]: Freeing up older rename of reg %i, "
- "[sn:%lli].\n",
- tid, (*hb_it).prevPhysReg, (*hb_it).instSeqNum);
-
- freeList->addReg((*hb_it).prevPhysReg);
- ++renameCommittedMaps;
-
- historyBuffer[tid].erase(hb_it--);
- }
-}
-
-template <class Impl>
-inline void
-DefaultRename<Impl>::renameSrcRegs(DynInstPtr &inst,unsigned tid)
-{
- assert(renameMap[tid] != 0);
-
- unsigned num_src_regs = inst->numSrcRegs();
-
- // Get the architectual register numbers from the source and
- // destination operands, and redirect them to the right register.
- // Will need to mark dependencies though.
- for (int src_idx = 0; src_idx < num_src_regs; src_idx++) {
- RegIndex src_reg = inst->srcRegIdx(src_idx);
-
- // Look up the source registers to get the phys. register they've
- // been renamed to, and set the sources to those registers.
- PhysRegIndex renamed_reg = renameMap[tid]->lookup(src_reg);
-
- DPRINTF(Rename, "[tid:%u]: Looking up arch reg %i, got "
- "physical reg %i.\n", tid, (int)src_reg,
- (int)renamed_reg);
-
- inst->renameSrcReg(src_idx, renamed_reg);
-
- // See if the register is ready or not.
- if (scoreboard->getReg(renamed_reg) == true) {
- DPRINTF(Rename, "[tid:%u]: Register is ready.\n", tid);
-
- inst->markSrcRegReady(src_idx);
- }
-
- ++renameRenameLookups;
- }
-}
-
-template <class Impl>
-inline void
-DefaultRename<Impl>::renameDestRegs(DynInstPtr &inst,unsigned tid)
-{
- typename RenameMap::RenameInfo rename_result;
-
- unsigned num_dest_regs = inst->numDestRegs();
-
- // Rename the destination registers.
- for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++) {
- RegIndex dest_reg = inst->destRegIdx(dest_idx);
-
- // Get the physical register that the destination will be
- // renamed to.
- rename_result = renameMap[tid]->rename(dest_reg);
-
- //Mark Scoreboard entry as not ready
- scoreboard->unsetReg(rename_result.first);
-
- DPRINTF(Rename, "[tid:%u]: Renaming arch reg %i to physical "
- "reg %i.\n", tid, (int)dest_reg,
- (int)rename_result.first);
-
- // Record the rename information so that a history can be kept.
- RenameHistory hb_entry(inst->seqNum, dest_reg,
- rename_result.first,
- rename_result.second);
-
- historyBuffer[tid].push_front(hb_entry);
-
- DPRINTF(Rename, "[tid:%u]: Adding instruction to history buffer, "
- "[sn:%lli].\n",tid,
- (*historyBuffer[tid].begin()).instSeqNum);
-
- // Tell the instruction to rename the appropriate destination
- // register (dest_idx) to the new physical register
- // (rename_result.first), and record the previous physical
- // register that the same logical register was renamed to
- // (rename_result.second).
- inst->renameDestReg(dest_idx,
- rename_result.first,
- rename_result.second);
-
- ++renameRenamedOperands;
- }
-}
-
-template <class Impl>
-inline int
-DefaultRename<Impl>::calcFreeROBEntries(unsigned tid)
-{
- int num_free = freeEntries[tid].robEntries -
- (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched);
-
- //DPRINTF(Rename,"[tid:%i]: %i rob free\n",tid,num_free);
-
- return num_free;
-}
-
-template <class Impl>
-inline int
-DefaultRename<Impl>::calcFreeIQEntries(unsigned tid)
-{
- int num_free = freeEntries[tid].iqEntries -
- (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched);
-
- //DPRINTF(Rename,"[tid:%i]: %i iq free\n",tid,num_free);
-
- return num_free;
-}
-
-template <class Impl>
-inline int
-DefaultRename<Impl>::calcFreeLSQEntries(unsigned tid)
-{
- int num_free = freeEntries[tid].lsqEntries -
- (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatchedToLSQ);
-
- //DPRINTF(Rename,"[tid:%i]: %i lsq free\n",tid,num_free);
-
- return num_free;
-}
-
-template <class Impl>
-unsigned
-DefaultRename<Impl>::validInsts()
-{
- unsigned inst_count = 0;
-
- for (int i=0; i<fromDecode->size; i++) {
- if (!fromDecode->insts[i]->squashed)
- inst_count++;
- }
-
- return inst_count;
-}
-
-template <class Impl>
-void
-DefaultRename<Impl>::readStallSignals(unsigned tid)
-{
- if (fromIEW->iewBlock[tid]) {
- stalls[tid].iew = true;
- }
-
- if (fromIEW->iewUnblock[tid]) {
- assert(stalls[tid].iew);
- stalls[tid].iew = false;
- }
-
- if (fromCommit->commitBlock[tid]) {
- stalls[tid].commit = true;
- }
-
- if (fromCommit->commitUnblock[tid]) {
- assert(stalls[tid].commit);
- stalls[tid].commit = false;
- }
-}
-
-template <class Impl>
-bool
-DefaultRename<Impl>::checkStall(unsigned tid)
-{
- bool ret_val = false;
-
- if (stalls[tid].iew) {
- DPRINTF(Rename,"[tid:%i]: Stall from IEW stage detected.\n", tid);
- ret_val = true;
- } else if (stalls[tid].commit) {
- DPRINTF(Rename,"[tid:%i]: Stall from Commit stage detected.\n", tid);
- ret_val = true;
- } else if (calcFreeROBEntries(tid) <= 0) {
- DPRINTF(Rename,"[tid:%i]: Stall: ROB has 0 free entries.\n", tid);
- ret_val = true;
- } else if (calcFreeIQEntries(tid) <= 0) {
- DPRINTF(Rename,"[tid:%i]: Stall: IQ has 0 free entries.\n", tid);
- ret_val = true;
- } else if (calcFreeLSQEntries(tid) <= 0) {
- DPRINTF(Rename,"[tid:%i]: Stall: LSQ has 0 free entries.\n", tid);
- ret_val = true;
- } else if (renameMap[tid]->numFreeEntries() <= 0) {
- DPRINTF(Rename,"[tid:%i]: Stall: RenameMap has 0 free entries.\n", tid);
- ret_val = true;
- } else if (renameStatus[tid] == SerializeStall &&
- (!emptyROB[tid] || instsInProgress[tid])) {
- DPRINTF(Rename,"[tid:%i]: Stall: Serialize stall and ROB is not "
- "empty.\n",
- tid);
- ret_val = true;
- }
-
- return ret_val;
-}
-
-template <class Impl>
-void
-DefaultRename<Impl>::readFreeEntries(unsigned tid)
-{
- bool updated = false;
- if (fromIEW->iewInfo[tid].usedIQ) {
- freeEntries[tid].iqEntries =
- fromIEW->iewInfo[tid].freeIQEntries;
- updated = true;
- }
-
- if (fromIEW->iewInfo[tid].usedLSQ) {
- freeEntries[tid].lsqEntries =
- fromIEW->iewInfo[tid].freeLSQEntries;
- updated = true;
- }
-
- if (fromCommit->commitInfo[tid].usedROB) {
- freeEntries[tid].robEntries =
- fromCommit->commitInfo[tid].freeROBEntries;
- emptyROB[tid] = fromCommit->commitInfo[tid].emptyROB;
- updated = true;
- }
-
- DPRINTF(Rename, "[tid:%i]: Free IQ: %i, Free ROB: %i, Free LSQ: %i\n",
- tid,
- freeEntries[tid].iqEntries,
- freeEntries[tid].robEntries,
- freeEntries[tid].lsqEntries);
-
- DPRINTF(Rename, "[tid:%i]: %i instructions not yet in ROB\n",
- tid, instsInProgress[tid]);
-}
-
-template <class Impl>
-bool
-DefaultRename<Impl>::checkSignalsAndUpdate(unsigned tid)
-{
- // Check if there's a squash signal, squash if there is
- // Check stall signals, block if necessary.
- // If status was blocked
- // check if stall conditions have passed
- // if so then go to unblocking
- // If status was Squashing
- // check if squashing is not high. Switch to running this cycle.
- // If status was serialize stall
- // check if ROB is empty and no insts are in flight to the ROB
-
- readFreeEntries(tid);
- readStallSignals(tid);
-
- if (fromCommit->commitInfo[tid].squash) {
- DPRINTF(Rename, "[tid:%u]: Squashing instructions due to squash from "
- "commit.\n", tid);
-
- squash(tid);
-
- return true;
- }
-
- if (fromCommit->commitInfo[tid].robSquashing) {
- DPRINTF(Rename, "[tid:%u]: ROB is still squashing.\n", tid);
-
- renameStatus[tid] = Squashing;
-
- return true;
- }
-
- if (checkStall(tid)) {
- return block(tid);
- }
-
- if (renameStatus[tid] == Blocked) {
- DPRINTF(Rename, "[tid:%u]: Done blocking, switching to unblocking.\n",
- tid);
-
- renameStatus[tid] = Unblocking;
-
- unblock(tid);
-
- return true;
- }
-
- if (renameStatus[tid] == Squashing) {
- // Switch status to running if rename isn't being told to block or
- // squash this cycle.
- DPRINTF(Rename, "[tid:%u]: Done squashing, switching to running.\n",
- tid);
-
- renameStatus[tid] = Running;
-
- return false;
- }
-
- if (renameStatus[tid] == SerializeStall) {
- // Stall ends once the ROB is free.
- DPRINTF(Rename, "[tid:%u]: Done with serialize stall, switching to "
- "unblocking.\n", tid);
-
- DynInstPtr serial_inst = serializeInst[tid];
-
- renameStatus[tid] = Unblocking;
-
- unblock(tid);
-
- DPRINTF(Rename, "[tid:%u]: Processing instruction [%lli] with "
- "PC %#x.\n",
- tid, serial_inst->seqNum, serial_inst->readPC());
-
- // Put instruction into queue here.
- serial_inst->clearSerializeBefore();
-
- if (!skidBuffer[tid].empty()) {
- skidBuffer[tid].push_front(serial_inst);
- } else {
- insts[tid].push_front(serial_inst);
- }
-
- DPRINTF(Rename, "[tid:%u]: Instruction must be processed by rename."
- " Adding to front of list.", tid);
-
- serializeInst[tid] = NULL;
-
- return true;
- }
-
- // If we've reached this point, we have not gotten any signals that
- // cause rename to change its status. Rename remains the same as before.
- return false;
-}
-
-template<class Impl>
-void
-DefaultRename<Impl>::serializeAfter(InstQueue &inst_list,
- unsigned tid)
-{
- if (inst_list.empty()) {
- // Mark a bit to say that I must serialize on the next instruction.
- serializeOnNextInst[tid] = true;
- return;
- }
-
- // Set the next instruction as serializing.
- inst_list.front()->setSerializeBefore();
-}
-
-template <class Impl>
-inline void
-DefaultRename<Impl>::incrFullStat(const FullSource &source)
-{
- switch (source) {
- case ROB:
- ++renameROBFullEvents;
- break;
- case IQ:
- ++renameIQFullEvents;
- break;
- case LSQ:
- ++renameLSQFullEvents;
- break;
- default:
- panic("Rename full stall stat should be incremented for a reason!");
- break;
- }
-}
-
-template <class Impl>
-void
-DefaultRename<Impl>::dumpHistory()
-{
- typename list<RenameHistory>::iterator buf_it;
-
- for (int i = 0; i < numThreads; i++) {
-
- buf_it = historyBuffer[i].begin();
-
- while (buf_it != historyBuffer[i].end()) {
- cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys "
- "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg,
- (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg);
-
- buf_it++;
- }
- }
-}
diff --git a/cpu/o3/rename_map.cc b/cpu/o3/rename_map.cc
deleted file mode 100644
index fc59058a1..000000000
--- a/cpu/o3/rename_map.cc
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <vector>
-
-#include "cpu/o3/rename_map.hh"
-
-using namespace std;
-
-// @todo: Consider making inline bool functions that determine if the
-// register is a logical int, logical fp, physical int, physical fp,
-// etc.
-
-SimpleRenameMap::~SimpleRenameMap()
-{
-}
-
-void
-SimpleRenameMap::init(unsigned _numLogicalIntRegs,
- unsigned _numPhysicalIntRegs,
- PhysRegIndex &ireg_idx,
-
- unsigned _numLogicalFloatRegs,
- unsigned _numPhysicalFloatRegs,
- PhysRegIndex &freg_idx,
-
- unsigned _numMiscRegs,
-
- RegIndex _intZeroReg,
- RegIndex _floatZeroReg,
-
- int map_id,
- bool bindRegs)
-{
- id = map_id;
-
- numLogicalIntRegs = _numLogicalIntRegs;
-
- numLogicalFloatRegs = _numLogicalFloatRegs;
-
- numPhysicalIntRegs = _numPhysicalIntRegs;
-
- numPhysicalFloatRegs = _numPhysicalFloatRegs;
-
- numMiscRegs = _numMiscRegs;
-
- intZeroReg = _intZeroReg;
- floatZeroReg = _floatZeroReg;
-
- DPRINTF(Rename, "Creating rename map %i. Phys: %i / %i, Float: "
- "%i / %i.\n", id, numLogicalIntRegs, numPhysicalIntRegs,
- numLogicalFloatRegs, numPhysicalFloatRegs);
-
- numLogicalRegs = numLogicalIntRegs + numLogicalFloatRegs;
-
- numPhysicalRegs = numPhysicalIntRegs + numPhysicalFloatRegs;
-
- //Create the rename maps
- intRenameMap.resize(numLogicalIntRegs);
- floatRenameMap.resize(numLogicalRegs);
-
- if (bindRegs) {
- DPRINTF(Rename, "Binding registers into rename map %i",id);
-
- // Initialize the entries in the integer rename map to point to the
- // physical registers of the same index
- for (RegIndex index = 0; index < numLogicalIntRegs; ++index)
- {
- intRenameMap[index].physical_reg = ireg_idx++;
- }
-
- // Initialize the entries in the floating point rename map to point to
- // the physical registers of the same index
- // Although the index refers purely to architected registers, because
- // the floating reg indices come after the integer reg indices, they
- // may exceed the size of a normal RegIndex (short).
- for (PhysRegIndex index = numLogicalIntRegs;
- index < numLogicalRegs; ++index)
- {
- floatRenameMap[index].physical_reg = freg_idx++;
- }
- } else {
- DPRINTF(Rename, "Binding registers into rename map %i",id);
-
- PhysRegIndex temp_ireg = ireg_idx;
-
- for (RegIndex index = 0; index < numLogicalIntRegs; ++index)
- {
- intRenameMap[index].physical_reg = temp_ireg++;
- }
-
- PhysRegIndex temp_freg = freg_idx;
-
- for (PhysRegIndex index = numLogicalIntRegs;
- index < numLogicalRegs; ++index)
- {
- floatRenameMap[index].physical_reg = temp_freg++;
- }
- }
-}
-
-void
-SimpleRenameMap::setFreeList(SimpleFreeList *fl_ptr)
-{
- freeList = fl_ptr;
-}
-
-
-SimpleRenameMap::RenameInfo
-SimpleRenameMap::rename(RegIndex arch_reg)
-{
- PhysRegIndex renamed_reg;
- PhysRegIndex prev_reg;
-
- if (arch_reg < numLogicalIntRegs) {
-
- // Record the current physical register that is renamed to the
- // requested architected register.
- prev_reg = intRenameMap[arch_reg].physical_reg;
-
- // If it's not referencing the zero register, then rename the
- // register.
- if (arch_reg != intZeroReg) {
- renamed_reg = freeList->getIntReg();
-
- intRenameMap[arch_reg].physical_reg = renamed_reg;
-
- assert(renamed_reg >= 0 && renamed_reg < numPhysicalIntRegs);
-
- } else {
- // Otherwise return the zero register so nothing bad happens.
- renamed_reg = intZeroReg;
- }
- } else if (arch_reg < numLogicalRegs) {
- // Record the current physical register that is renamed to the
- // requested architected register.
- prev_reg = floatRenameMap[arch_reg].physical_reg;
-
- // If it's not referencing the zero register, then rename the
- // register.
- if (arch_reg != floatZeroReg) {
- renamed_reg = freeList->getFloatReg();
-
- floatRenameMap[arch_reg].physical_reg = renamed_reg;
-
- assert(renamed_reg < numPhysicalRegs &&
- renamed_reg >= numPhysicalIntRegs);
- } else {
- // Otherwise return the zero register so nothing bad happens.
- renamed_reg = floatZeroReg;
- }
- } else {
- // Subtract off the base offset for miscellaneous registers.
- arch_reg = arch_reg - numLogicalRegs;
-
- // No renaming happens to the misc. registers. They are
- // simply the registers that come after all the physical
- // registers; thus take the base architected register and add
- // the physical registers to it.
- renamed_reg = arch_reg + numPhysicalRegs;
-
- // Set the previous register to the same register; mainly it must be
- // known that the prev reg was outside the range of normal registers
- // so the free list can avoid adding it.
- prev_reg = renamed_reg;
-
- assert(renamed_reg < numPhysicalRegs + numMiscRegs);
- }
-
- return RenameInfo(renamed_reg, prev_reg);
-}
-
-PhysRegIndex
-SimpleRenameMap::lookup(RegIndex arch_reg)
-{
- if (arch_reg < numLogicalIntRegs) {
- return intRenameMap[arch_reg].physical_reg;
- } else if (arch_reg < numLogicalRegs) {
- return floatRenameMap[arch_reg].physical_reg;
- } else {
- // Subtract off the misc registers offset.
- arch_reg = arch_reg - numLogicalRegs;
-
- // Misc. regs don't rename, so simply add the base arch reg to
- // the number of physical registers.
- return numPhysicalRegs + arch_reg;
- }
-}
-
-void
-SimpleRenameMap::setEntry(RegIndex arch_reg, PhysRegIndex renamed_reg)
-{
- // In this implementation the miscellaneous registers do not
- // actually rename, so this function does not allow you to try to
- // change their mappings.
- if (arch_reg < numLogicalIntRegs) {
- DPRINTF(Rename, "Rename Map: Integer register %i being set to %i.\n",
- (int)arch_reg, renamed_reg);
-
- intRenameMap[arch_reg].physical_reg = renamed_reg;
- } else if (arch_reg < numLogicalIntRegs + numLogicalFloatRegs) {
- DPRINTF(Rename, "Rename Map: Float register %i being set to %i.\n",
- (int)arch_reg - numLogicalIntRegs, renamed_reg);
-
- floatRenameMap[arch_reg].physical_reg = renamed_reg;
- }
-}
-
-int
-SimpleRenameMap::numFreeEntries()
-{
- int free_int_regs = freeList->numFreeIntRegs();
- int free_float_regs = freeList->numFreeFloatRegs();
-
- if (free_int_regs < free_float_regs) {
- return free_int_regs;
- } else {
- return free_float_regs;
- }
-}
diff --git a/cpu/o3/rename_map.hh b/cpu/o3/rename_map.hh
deleted file mode 100644
index 1ac627264..000000000
--- a/cpu/o3/rename_map.hh
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-// Todo: Create destructor.
-// Have it so that there's a more meaningful name given to the variable
-// that marks the beginning of the FP registers.
-
-#ifndef __CPU_O3_RENAME_MAP_HH__
-#define __CPU_O3_RENAME_MAP_HH__
-
-#include <iostream>
-#include <utility>
-#include <vector>
-
-#include "cpu/o3/free_list.hh"
-//For RegIndex
-#include "arch/isa_traits.hh"
-
-class SimpleRenameMap
-{
- protected:
- typedef TheISA::RegIndex RegIndex;
- public:
- /**
- * Pair of a logical register and a physical register. Tells the
- * previous mapping of a logical register to a physical register.
- * Used to roll back the rename map to a previous state.
- */
- typedef std::pair<RegIndex, PhysRegIndex> UnmapInfo;
-
- /**
- * Pair of a physical register and a physical register. Used to
- * return the physical register that a logical register has been
- * renamed to, and the previous physical register that the same
- * logical register was previously mapped to.
- */
- typedef std::pair<PhysRegIndex, PhysRegIndex> RenameInfo;
-
- public:
- /** Default constructor. init() must be called prior to use. */
- SimpleRenameMap() {};
-
- /** Destructor. */
- ~SimpleRenameMap();
-
- /** Initializes rename map with given parameters. */
- void init(unsigned _numLogicalIntRegs,
- unsigned _numPhysicalIntRegs,
- PhysRegIndex &_int_reg_start,
-
- unsigned _numLogicalFloatRegs,
- unsigned _numPhysicalFloatRegs,
- PhysRegIndex &_float_reg_start,
-
- unsigned _numMiscRegs,
-
- RegIndex _intZeroReg,
- RegIndex _floatZeroReg,
-
- int id,
- bool bindRegs);
-
- /** Sets the free list used with this rename map. */
- void setFreeList(SimpleFreeList *fl_ptr);
-
- //Tell rename map to get a free physical register for a given
- //architected register. Not sure it should have a return value,
- //but perhaps it should have some sort of fault in case there are
- //no free registers.
- RenameInfo rename(RegIndex arch_reg);
-
- PhysRegIndex lookup(RegIndex phys_reg);
-
- /**
- * Marks the given register as ready, meaning that its value has been
- * calculated and written to the register file.
- * @param ready_reg The index of the physical register that is now ready.
- */
- void setEntry(RegIndex arch_reg, PhysRegIndex renamed_reg);
-
- int numFreeEntries();
-
- private:
- /** Rename Map ID */
- int id;
-
- /** Number of logical integer registers. */
- int numLogicalIntRegs;
-
- /** Number of physical integer registers. */
- int numPhysicalIntRegs;
-
- /** Number of logical floating point registers. */
- int numLogicalFloatRegs;
-
- /** Number of physical floating point registers. */
- int numPhysicalFloatRegs;
-
- /** Number of miscellaneous registers. */
- int numMiscRegs;
-
- /** Number of logical integer + float registers. */
- int numLogicalRegs;
-
- /** Number of physical integer + float registers. */
- int numPhysicalRegs;
-
- /** The integer zero register. This implementation assumes it is always
- * zero and never can be anything else.
- */
- RegIndex intZeroReg;
-
- /** The floating point zero register. This implementation assumes it is
- * always zero and never can be anything else.
- */
- RegIndex floatZeroReg;
-
- class RenameEntry
- {
- public:
- PhysRegIndex physical_reg;
- bool valid;
-
- RenameEntry()
- : physical_reg(0), valid(false)
- { }
- };
-
- private:
- /** Integer rename map. */
- std::vector<RenameEntry> intRenameMap;
-
- /** Floating point rename map. */
- std::vector<RenameEntry> floatRenameMap;
-
- private:
- /** Free list interface. */
- SimpleFreeList *freeList;
-};
-
-#endif //__CPU_O3_RENAME_MAP_HH__
diff --git a/cpu/o3/rob.cc b/cpu/o3/rob.cc
deleted file mode 100644
index c10f782fd..000000000
--- a/cpu/o3/rob.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/o3/alpha_dyn_inst.hh"
-#include "cpu/o3/alpha_impl.hh"
-#include "cpu/o3/rob_impl.hh"
-
-// Force instantiation of InstructionQueue.
-template class ROB<AlphaSimpleImpl>;
diff --git a/cpu/o3/rob.hh b/cpu/o3/rob.hh
deleted file mode 100644
index bdbdde32f..000000000
--- a/cpu/o3/rob.hh
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_ROB_HH__
-#define __CPU_O3_ROB_HH__
-
-#include <string>
-#include <utility>
-#include <vector>
-
-/**
- * ROB class. The ROB is largely what drives squashing.
- */
-template <class Impl>
-class ROB
-{
- protected:
- typedef TheISA::RegIndex RegIndex;
- public:
- //Typedefs from the Impl.
- typedef typename Impl::FullCPU FullCPU;
- typedef typename Impl::DynInstPtr DynInstPtr;
-
- typedef std::pair<RegIndex, PhysRegIndex> UnmapInfo;
- typedef typename std::list<DynInstPtr>::iterator InstIt;
-
- /** Possible ROB statuses. */
- enum Status {
- Running,
- Idle,
- ROBSquashing
- };
-
- /** SMT ROB Sharing Policy */
- enum ROBPolicy{
- Dynamic,
- Partitioned,
- Threshold
- };
-
- private:
- /** Per-thread ROB status. */
- Status robStatus[Impl::MaxThreads];
-
- /** ROB resource sharing policy for SMT mode. */
- ROBPolicy robPolicy;
-
- public:
- /** ROB constructor.
- * @param _numEntries Number of entries in ROB.
- * @param _squashWidth Number of instructions that can be squashed in a
- * single cycle.
- * @param _smtROBPolicy ROB Partitioning Scheme for SMT.
- * @param _smtROBThreshold Max Resources(by %) a thread can have in the ROB.
- * @param _numThreads The number of active threads.
- */
- ROB(unsigned _numEntries, unsigned _squashWidth, std::string smtROBPolicy,
- unsigned _smtROBThreshold, unsigned _numThreads);
-
- std::string name() const;
-
- /** Function to set the CPU pointer, necessary due to which object the ROB
- * is created within.
- * @param cpu_ptr Pointer to the implementation specific full CPU object.
- */
- void setCPU(FullCPU *cpu_ptr);
-
- /** Sets pointer to the list of active threads.
- * @param at_ptr Pointer to the list of active threads.
- */
- void setActiveThreads(std::list<unsigned>* at_ptr);
-
- /** Switches out the ROB. */
- void switchOut();
-
- /** Takes over another CPU's thread. */
- void takeOverFrom();
-
- /** Function to insert an instruction into the ROB. Note that whatever
- * calls this function must ensure that there is enough space within the
- * ROB for the new instruction.
- * @param inst The instruction being inserted into the ROB.
- */
- void insertInst(DynInstPtr &inst);
-
- /** Returns pointer to the head instruction within the ROB. There is
- * no guarantee as to the return value if the ROB is empty.
- * @retval Pointer to the DynInst that is at the head of the ROB.
- */
-// DynInstPtr readHeadInst();
-
- /** Returns a pointer to the head instruction of a specific thread within
- * the ROB.
- * @return Pointer to the DynInst that is at the head of the ROB.
- */
- DynInstPtr readHeadInst(unsigned tid);
-
- /** Returns pointer to the tail instruction within the ROB. There is
- * no guarantee as to the return value if the ROB is empty.
- * @retval Pointer to the DynInst that is at the tail of the ROB.
- */
-// DynInstPtr readTailInst();
-
- /** Returns a pointer to the tail instruction of a specific thread within
- * the ROB.
- * @return Pointer to the DynInst that is at the tail of the ROB.
- */
- DynInstPtr readTailInst(unsigned tid);
-
- /** Retires the head instruction, removing it from the ROB. */
-// void retireHead();
-
- /** Retires the head instruction of a specific thread, removing it from the
- * ROB.
- */
- void retireHead(unsigned tid);
-
- /** Is the oldest instruction across all threads ready. */
-// bool isHeadReady();
-
- /** Is the oldest instruction across a particular thread ready. */
- bool isHeadReady(unsigned tid);
-
- /** Is there any commitable head instruction across all threads ready. */
- bool canCommit();
-
- /** Re-adjust ROB partitioning. */
- void resetEntries();
-
- /** Number of entries needed For 'num_threads' amount of threads. */
- int entryAmount(int num_threads);
-
- /** Returns the number of total free entries in the ROB. */
- unsigned numFreeEntries();
-
- /** Returns the number of free entries in a specific ROB paritition. */
- unsigned numFreeEntries(unsigned tid);
-
- /** Returns the maximum number of entries for a specific thread. */
- unsigned getMaxEntries(unsigned tid)
- { return maxEntries[tid]; }
-
- /** Returns the number of entries being used by a specific thread. */
- unsigned getThreadEntries(unsigned tid)
- { return threadEntries[tid]; }
-
- /** Returns if the ROB is full. */
- bool isFull()
- { return numInstsInROB == numEntries; }
-
- /** Returns if a specific thread's partition is full. */
- bool isFull(unsigned tid)
- { return threadEntries[tid] == numEntries; }
-
- /** Returns if the ROB is empty. */
- bool isEmpty()
- { return numInstsInROB == 0; }
-
- /** Returns if a specific thread's partition is empty. */
- bool isEmpty(unsigned tid)
- { return threadEntries[tid] == 0; }
-
- /** Executes the squash, marking squashed instructions. */
- void doSquash(unsigned tid);
-
- /** Squashes all instructions younger than the given sequence number for
- * the specific thread.
- */
- void squash(InstSeqNum squash_num, unsigned tid);
-
- /** Updates the head instruction with the new oldest instruction. */
- void updateHead();
-
- /** Updates the tail instruction with the new youngest instruction. */
- void updateTail();
-
- /** Reads the PC of the oldest head instruction. */
-// uint64_t readHeadPC();
-
- /** Reads the PC of the head instruction of a specific thread. */
-// uint64_t readHeadPC(unsigned tid);
-
- /** Reads the next PC of the oldest head instruction. */
-// uint64_t readHeadNextPC();
-
- /** Reads the next PC of the head instruction of a specific thread. */
-// uint64_t readHeadNextPC(unsigned tid);
-
- /** Reads the sequence number of the oldest head instruction. */
-// InstSeqNum readHeadSeqNum();
-
- /** Reads the sequence number of the head instruction of a specific thread.
- */
-// InstSeqNum readHeadSeqNum(unsigned tid);
-
- /** Reads the PC of the youngest tail instruction. */
-// uint64_t readTailPC();
-
- /** Reads the PC of the tail instruction of a specific thread. */
-// uint64_t readTailPC(unsigned tid);
-
- /** Reads the sequence number of the youngest tail instruction. */
-// InstSeqNum readTailSeqNum();
-
- /** Reads the sequence number of tail instruction of a specific thread. */
-// InstSeqNum readTailSeqNum(unsigned tid);
-
- /** Checks if the ROB is still in the process of squashing instructions.
- * @retval Whether or not the ROB is done squashing.
- */
- bool isDoneSquashing(unsigned tid) const
- { return doneSquashing[tid]; }
-
- /** Checks if the ROB is still in the process of squashing instructions for
- * any thread.
- */
- bool isDoneSquashing();
-
- /** This is more of a debugging function than anything. Use
- * numInstsInROB to get the instructions in the ROB unless you are
- * double checking that variable.
- */
- int countInsts();
-
- /** This is more of a debugging function than anything. Use
- * threadEntries to get the instructions in the ROB unless you are
- * double checking that variable.
- */
- int countInsts(unsigned tid);
-
- private:
- /** Pointer to the CPU. */
- FullCPU *cpu;
-
- /** Active Threads in CPU */
- std::list<unsigned>* activeThreads;
-
- /** Number of instructions in the ROB. */
- unsigned numEntries;
-
- /** Entries Per Thread */
- unsigned threadEntries[Impl::MaxThreads];
-
- /** Max Insts a Thread Can Have in the ROB */
- unsigned maxEntries[Impl::MaxThreads];
-
- /** ROB List of Instructions */
- std::list<DynInstPtr> instList[Impl::MaxThreads];
-
- /** Number of instructions that can be squashed in a single cycle. */
- unsigned squashWidth;
-
- public:
- /** Iterator pointing to the instruction which is the last instruction
- * in the ROB. This may at times be invalid (ie when the ROB is empty),
- * however it should never be incorrect.
- */
- InstIt tail;
-
- /** Iterator pointing to the instruction which is the first instruction in
- * in the ROB*/
- InstIt head;
-
- private:
- /** Iterator used for walking through the list of instructions when
- * squashing. Used so that there is persistent state between cycles;
- * when squashing, the instructions are marked as squashed but not
- * immediately removed, meaning the tail iterator remains the same before
- * and after a squash.
- * This will always be set to cpu->instList.end() if it is invalid.
- */
- InstIt squashIt[Impl::MaxThreads];
-
- public:
- /** Number of instructions in the ROB. */
- int numInstsInROB;
-
- /** Dummy instruction returned if there are no insts left. */
- DynInstPtr dummyInst;
-
- private:
- /** The sequence number of the squashed instruction. */
- InstSeqNum squashedSeqNum;
-
- /** Is the ROB done squashing. */
- bool doneSquashing[Impl::MaxThreads];
-
- /** Number of active threads. */
- unsigned numThreads;
-};
-
-#endif //__CPU_O3_ROB_HH__
diff --git a/cpu/o3/rob_impl.hh b/cpu/o3/rob_impl.hh
deleted file mode 100644
index 25e0c80fd..000000000
--- a/cpu/o3/rob_impl.hh
+++ /dev/null
@@ -1,691 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config/full_system.hh"
-#include "cpu/o3/rob.hh"
-
-using namespace std;
-
-template <class Impl>
-ROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth,
- string _smtROBPolicy, unsigned _smtROBThreshold,
- unsigned _numThreads)
- : numEntries(_numEntries),
- squashWidth(_squashWidth),
- numInstsInROB(0),
- squashedSeqNum(0),
- numThreads(_numThreads)
-{
- for (int tid=0; tid < numThreads; tid++) {
- doneSquashing[tid] = true;
- threadEntries[tid] = 0;
- }
-
- string policy = _smtROBPolicy;
-
- //Convert string to lowercase
- std::transform(policy.begin(), policy.end(), policy.begin(),
- (int(*)(int)) tolower);
-
- //Figure out rob policy
- if (policy == "dynamic") {
- robPolicy = Dynamic;
-
- //Set Max Entries to Total ROB Capacity
- for (int i = 0; i < numThreads; i++) {
- maxEntries[i]=numEntries;
- }
-
- } else if (policy == "partitioned") {
- robPolicy = Partitioned;
- DPRINTF(Fetch, "ROB sharing policy set to Partitioned\n");
-
- //@todo:make work if part_amt doesnt divide evenly.
- int part_amt = numEntries / numThreads;
-
- //Divide ROB up evenly
- for (int i = 0; i < numThreads; i++) {
- maxEntries[i]=part_amt;
- }
-
- } else if (policy == "threshold") {
- robPolicy = Threshold;
- DPRINTF(Fetch, "ROB sharing policy set to Threshold\n");
-
- int threshold = _smtROBThreshold;;
-
- //Divide up by threshold amount
- for (int i = 0; i < numThreads; i++) {
- maxEntries[i]=threshold;
- }
- } else {
- assert(0 && "Invalid ROB Sharing Policy.Options Are:{Dynamic,"
- "Partitioned, Threshold}");
- }
-}
-
-template <class Impl>
-std::string
-ROB<Impl>::name() const
-{
- return cpu->name() + ".rob";
-}
-
-template <class Impl>
-void
-ROB<Impl>::setCPU(FullCPU *cpu_ptr)
-{
- cpu = cpu_ptr;
-
- // Set the per-thread iterators to the end of the instruction list.
- for (int i=0; i < numThreads;i++) {
- squashIt[i] = instList[i].end();
- }
-
- // Initialize the "universal" ROB head & tail point to invalid
- // pointers
- head = instList[0].end();
- tail = instList[0].end();
-}
-
-template <class Impl>
-void
-ROB<Impl>::setActiveThreads(list<unsigned> *at_ptr)
-{
- DPRINTF(ROB, "Setting active threads list pointer.\n");
- activeThreads = at_ptr;
-}
-
-template <class Impl>
-void
-ROB<Impl>::switchOut()
-{
- for (int tid = 0; tid < numThreads; tid++) {
- instList[tid].clear();
- }
-}
-
-template <class Impl>
-void
-ROB<Impl>::takeOverFrom()
-{
- for (int tid=0; tid < numThreads; tid++) {
- doneSquashing[tid] = true;
- threadEntries[tid] = 0;
- squashIt[tid] = instList[tid].end();
- }
- numInstsInROB = 0;
-
- // Initialize the "universal" ROB head & tail point to invalid
- // pointers
- head = instList[0].end();
- tail = instList[0].end();
-}
-
-template <class Impl>
-void
-ROB<Impl>::resetEntries()
-{
- if (robPolicy != Dynamic || numThreads > 1) {
- int active_threads = (*activeThreads).size();
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
- list<unsigned>::iterator list_end = (*activeThreads).end();
-
- while (threads != list_end) {
- if (robPolicy == Partitioned) {
- maxEntries[*threads++] = numEntries / active_threads;
- } else if (robPolicy == Threshold && active_threads == 1) {
- maxEntries[*threads++] = numEntries;
- }
- }
- }
-}
-
-template <class Impl>
-int
-ROB<Impl>::entryAmount(int num_threads)
-{
- if (robPolicy == Partitioned) {
- return numEntries / num_threads;
- } else {
- return 0;
- }
-}
-
-template <class Impl>
-int
-ROB<Impl>::countInsts()
-{
- int total=0;
-
- for (int i=0;i < numThreads;i++)
- total += countInsts(i);
-
- return total;
-}
-
-template <class Impl>
-int
-ROB<Impl>::countInsts(unsigned tid)
-{
- return instList[tid].size();
-}
-
-template <class Impl>
-void
-ROB<Impl>::insertInst(DynInstPtr &inst)
-{
- //assert(numInstsInROB == countInsts());
- assert(inst);
-
- DPRINTF(ROB, "Adding inst PC %#x to the ROB.\n", inst->readPC());
-
- assert(numInstsInROB != numEntries);
-
- int tid = inst->threadNumber;
-
- instList[tid].push_back(inst);
-
- //Set Up head iterator if this is the 1st instruction in the ROB
- if (numInstsInROB == 0) {
- head = instList[tid].begin();
- assert((*head) == inst);
- }
-
- //Must Decrement for iterator to actually be valid since __.end()
- //actually points to 1 after the last inst
- tail = instList[tid].end();
- tail--;
-
- inst->setInROB();
-
- ++numInstsInROB;
- ++threadEntries[tid];
-
- assert((*tail) == inst);
-
- DPRINTF(ROB, "[tid:%i] Now has %d instructions.\n", tid, threadEntries[tid]);
-}
-
-// Whatever calls this function needs to ensure that it properly frees up
-// registers prior to this function.
-/*
-template <class Impl>
-void
-ROB<Impl>::retireHead()
-{
- //assert(numInstsInROB == countInsts());
- assert(numInstsInROB > 0);
-
- int tid = (*head)->threadNumber;
-
- retireHead(tid);
-
- if (numInstsInROB == 0) {
- tail = instList[tid].end();
- }
-}
-*/
-
-template <class Impl>
-void
-ROB<Impl>::retireHead(unsigned tid)
-{
- //assert(numInstsInROB == countInsts());
- assert(numInstsInROB > 0);
-
- // Get the head ROB instruction.
- InstIt head_it = instList[tid].begin();
-
- DynInstPtr head_inst = (*head_it);
-
- assert(head_inst->readyToCommit());
-
- DPRINTF(ROB, "[tid:%u]: Retiring head instruction, "
- "instruction PC %#x,[sn:%lli]\n", tid, head_inst->readPC(),
- head_inst->seqNum);
-
- --numInstsInROB;
- --threadEntries[tid];
-
- head_inst->removeInROB();
- head_inst->setCommitted();
-
- instList[tid].erase(head_it);
-
- //Update "Global" Head of ROB
- updateHead();
-
- // @todo: A special case is needed if the instruction being
- // retired is the only instruction in the ROB; otherwise the tail
- // iterator will become invalidated.
- cpu->removeFrontInst(head_inst);
-}
-/*
-template <class Impl>
-bool
-ROB<Impl>::isHeadReady()
-{
- if (numInstsInROB != 0) {
- return (*head)->readyToCommit();
- }
-
- return false;
-}
-*/
-template <class Impl>
-bool
-ROB<Impl>::isHeadReady(unsigned tid)
-{
- if (threadEntries[tid] != 0) {
- return instList[tid].front()->readyToCommit();
- }
-
- return false;
-}
-
-template <class Impl>
-bool
-ROB<Impl>::canCommit()
-{
- //@todo: set ActiveThreads through ROB or CPU
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- if (isHeadReady(tid)) {
- return true;
- }
- }
-
- return false;
-}
-
-template <class Impl>
-unsigned
-ROB<Impl>::numFreeEntries()
-{
- //assert(numInstsInROB == countInsts());
-
- return numEntries - numInstsInROB;
-}
-
-template <class Impl>
-unsigned
-ROB<Impl>::numFreeEntries(unsigned tid)
-{
- return maxEntries[tid] - threadEntries[tid];
-}
-
-template <class Impl>
-void
-ROB<Impl>::doSquash(unsigned tid)
-{
- DPRINTF(ROB, "[tid:%u]: Squashing instructions until [sn:%i].\n",
- tid, squashedSeqNum);
-
- assert(squashIt[tid] != instList[tid].end());
-
- if ((*squashIt[tid])->seqNum < squashedSeqNum) {
- DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
- tid);
-
- squashIt[tid] = instList[tid].end();
-
- doneSquashing[tid] = true;
- return;
- }
-
- bool robTailUpdate = false;
-
- for (int numSquashed = 0;
- numSquashed < squashWidth &&
- squashIt[tid] != instList[tid].end() &&
- (*squashIt[tid])->seqNum > squashedSeqNum;
- ++numSquashed)
- {
- DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %#x, seq num %i.\n",
- (*squashIt[tid])->threadNumber,
- (*squashIt[tid])->readPC(),
- (*squashIt[tid])->seqNum);
-
- // Mark the instruction as squashed, and ready to commit so that
- // it can drain out of the pipeline.
- (*squashIt[tid])->setSquashed();
-
- (*squashIt[tid])->setCanCommit();
-
-
- if (squashIt[tid] == instList[tid].begin()) {
- DPRINTF(ROB, "Reached head of instruction list while "
- "squashing.\n");
-
- squashIt[tid] = instList[tid].end();
-
- doneSquashing[tid] = true;
-
- return;
- }
-
- InstIt tail_thread = instList[tid].end();
- tail_thread--;
-
- if ((*squashIt[tid]) == (*tail_thread))
- robTailUpdate = true;
-
- squashIt[tid]--;
- }
-
-
- // Check if ROB is done squashing.
- if ((*squashIt[tid])->seqNum <= squashedSeqNum) {
- DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
- tid);
-
- squashIt[tid] = instList[tid].end();
-
- doneSquashing[tid] = true;
- }
-
- if (robTailUpdate) {
- updateTail();
- }
-}
-
-
-template <class Impl>
-void
-ROB<Impl>::updateHead()
-{
- DynInstPtr head_inst;
- InstSeqNum lowest_num = 0;
- bool first_valid = true;
-
- // @todo: set ActiveThreads through ROB or CPU
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- unsigned thread_num = *threads++;
-
- if (instList[thread_num].empty())
- continue;
-
- if (first_valid) {
- head = instList[thread_num].begin();
- lowest_num = (*head)->seqNum;
- first_valid = false;
- continue;
- }
-
- InstIt head_thread = instList[thread_num].begin();
-
- DynInstPtr head_inst = (*head_thread);
-
- assert(head_inst != 0);
-
- if (head_inst->seqNum < lowest_num) {
- head = head_thread;
- lowest_num = head_inst->seqNum;
- }
- }
-
- if (first_valid) {
- head = instList[0].end();
- }
-
-}
-
-template <class Impl>
-void
-ROB<Impl>::updateTail()
-{
- tail = instList[0].end();
- bool first_valid = true;
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
-
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
-
- if (instList[tid].empty()) {
- continue;
- }
-
- // If this is the first valid then assign w/out
- // comparison
- if (first_valid) {
- tail = instList[tid].end();
- tail--;
- first_valid = false;
- continue;
- }
-
- // Assign new tail if this thread's tail is younger
- // than our current "tail high"
- InstIt tail_thread = instList[tid].end();
- tail_thread--;
-
- if ((*tail_thread)->seqNum > (*tail)->seqNum) {
- tail = tail_thread;
- }
- }
-}
-
-
-template <class Impl>
-void
-ROB<Impl>::squash(InstSeqNum squash_num,unsigned tid)
-{
- if (isEmpty()) {
- DPRINTF(ROB, "Does not need to squash due to being empty "
- "[sn:%i]\n",
- squash_num);
-
- return;
- }
-
- DPRINTF(ROB, "Starting to squash within the ROB.\n");
-
- robStatus[tid] = ROBSquashing;
-
- doneSquashing[tid] = false;
-
- squashedSeqNum = squash_num;
-
- if (!instList[tid].empty()) {
- InstIt tail_thread = instList[tid].end();
- tail_thread--;
-
- squashIt[tid] = tail_thread;
-
- doSquash(tid);
- }
-}
-/*
-template <class Impl>
-typename Impl::DynInstPtr
-ROB<Impl>::readHeadInst()
-{
- if (numInstsInROB != 0) {
- assert((*head)->isInROB()==true);
- return *head;
- } else {
- return dummyInst;
- }
-}
-*/
-template <class Impl>
-typename Impl::DynInstPtr
-ROB<Impl>::readHeadInst(unsigned tid)
-{
- if (threadEntries[tid] != 0) {
- InstIt head_thread = instList[tid].begin();
-
- assert((*head_thread)->isInROB()==true);
-
- return *head_thread;
- } else {
- return dummyInst;
- }
-}
-/*
-template <class Impl>
-uint64_t
-ROB<Impl>::readHeadPC()
-{
- //assert(numInstsInROB == countInsts());
-
- DynInstPtr head_inst = *head;
-
- return head_inst->readPC();
-}
-
-template <class Impl>
-uint64_t
-ROB<Impl>::readHeadPC(unsigned tid)
-{
- //assert(numInstsInROB == countInsts());
- InstIt head_thread = instList[tid].begin();
-
- return (*head_thread)->readPC();
-}
-
-
-template <class Impl>
-uint64_t
-ROB<Impl>::readHeadNextPC()
-{
- //assert(numInstsInROB == countInsts());
-
- DynInstPtr head_inst = *head;
-
- return head_inst->readNextPC();
-}
-
-template <class Impl>
-uint64_t
-ROB<Impl>::readHeadNextPC(unsigned tid)
-{
- //assert(numInstsInROB == countInsts());
- InstIt head_thread = instList[tid].begin();
-
- return (*head_thread)->readNextPC();
-}
-
-template <class Impl>
-InstSeqNum
-ROB<Impl>::readHeadSeqNum()
-{
- //assert(numInstsInROB == countInsts());
- DynInstPtr head_inst = *head;
-
- return head_inst->seqNum;
-}
-
-template <class Impl>
-InstSeqNum
-ROB<Impl>::readHeadSeqNum(unsigned tid)
-{
- InstIt head_thread = instList[tid].begin();
-
- return ((*head_thread)->seqNum);
-}
-
-template <class Impl>
-typename Impl::DynInstPtr
-ROB<Impl>::readTailInst()
-{
- //assert(numInstsInROB == countInsts());
- //assert(tail != instList[0].end());
-
- return (*tail);
-}
-*/
-template <class Impl>
-typename Impl::DynInstPtr
-ROB<Impl>::readTailInst(unsigned tid)
-{
- //assert(tail_thread[tid] != instList[tid].end());
-
- InstIt tail_thread = instList[tid].end();
- tail_thread--;
-
- return *tail_thread;
-}
-
-/*
-template <class Impl>
-uint64_t
-ROB<Impl>::readTailPC()
-{
- //assert(numInstsInROB == countInsts());
-
- //assert(tail != instList[0].end());
-
- return (*tail)->readPC();
-}
-
-template <class Impl>
-uint64_t
-ROB<Impl>::readTailPC(unsigned tid)
-{
- //assert(tail_thread[tid] != instList[tid].end());
-
- InstIt tail_thread = instList[tid].end();
- tail_thread--;
-
- return (*tail_thread)->readPC();
-}
-
-template <class Impl>
-InstSeqNum
-ROB<Impl>::readTailSeqNum()
-{
- // Return the last sequence number that has not been squashed. Other
- // stages can use it to squash any instructions younger than the current
- // tail.
- return (*tail)->seqNum;
-}
-
-template <class Impl>
-InstSeqNum
-ROB<Impl>::readTailSeqNum(unsigned tid)
-{
- // Return the last sequence number that has not been squashed. Other
- // stages can use it to squash any instructions younger than the current
- // tail.
- // assert(tail_thread[tid] != instList[tid].end());
-
- InstIt tail_thread = instList[tid].end();
- tail_thread--;
-
- return (*tail_thread)->seqNum;
-}
-*/
diff --git a/cpu/o3/sat_counter.hh b/cpu/o3/sat_counter.hh
deleted file mode 100644
index d01fd93ce..000000000
--- a/cpu/o3/sat_counter.hh
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2005-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_SAT_COUNTER_HH__
-#define __CPU_O3_SAT_COUNTER_HH__
-
-#include "sim/host.hh"
-
-/**
- * Private counter class for the internal saturating counters.
- * Implements an n bit saturating counter and provides methods to
- * increment, decrement, and read it.
- * @todo Consider making this something that more closely mimics a
- * built in class so you can use ++ or --.
- */
-class SatCounter
-{
- public:
- /**
- * Constructor for the counter.
- */
- SatCounter()
- : initialVal(0), counter(0)
- { }
-
- /**
- * Constructor for the counter.
- * @param bits How many bits the counter will have.
- */
- SatCounter(unsigned bits)
- : initialVal(0), maxVal((1 << bits) - 1), counter(0)
- { }
-
- /**
- * Constructor for the counter.
- * @param bits How many bits the counter will have.
- * @param initial_val Starting value for each counter.
- */
- SatCounter(unsigned bits, uint8_t initial_val)
- : initialVal(initialVal), maxVal((1 << bits) - 1), counter(initial_val)
- {
- // Check to make sure initial value doesn't exceed the max
- // counter value.
- if (initial_val > maxVal) {
- fatal("BP: Initial counter value exceeds max size.");
- }
- }
-
- /**
- * Sets the number of bits.
- */
- void setBits(unsigned bits) { maxVal = (1 << bits) - 1; }
-
- void reset() { counter = initialVal; }
-
- /**
- * Increments the counter's current value.
- */
- void increment()
- {
- if (counter < maxVal) {
- ++counter;
- }
- }
-
- /**
- * Decrements the counter's current value.
- */
- void decrement()
- {
- if (counter > 0) {
- --counter;
- }
- }
-
- /**
- * Read the counter's value.
- */
- const uint8_t read() const
- { return counter; }
-
- private:
- uint8_t initialVal;
- uint8_t maxVal;
- uint8_t counter;
-};
-
-#endif // __CPU_O3_SAT_COUNTER_HH__
diff --git a/cpu/o3/scoreboard.cc b/cpu/o3/scoreboard.cc
deleted file mode 100644
index b0e433620..000000000
--- a/cpu/o3/scoreboard.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/o3/scoreboard.hh"
-
-Scoreboard::Scoreboard(unsigned activeThreads,
- unsigned _numLogicalIntRegs,
- unsigned _numPhysicalIntRegs,
- unsigned _numLogicalFloatRegs,
- unsigned _numPhysicalFloatRegs,
- unsigned _numMiscRegs,
- unsigned _zeroRegIdx)
- : numLogicalIntRegs(_numLogicalIntRegs),
- numPhysicalIntRegs(_numPhysicalIntRegs),
- numLogicalFloatRegs(_numLogicalFloatRegs),
- numPhysicalFloatRegs(_numPhysicalFloatRegs),
- numMiscRegs(_numMiscRegs),
- zeroRegIdx(_zeroRegIdx)
-{
- //Get Register Sizes
- numLogicalRegs = numLogicalIntRegs + numLogicalFloatRegs;
- numPhysicalRegs = numPhysicalIntRegs + numPhysicalFloatRegs;
-
- //Resize scoreboard appropriately
- regScoreBoard.resize(numPhysicalRegs + (numMiscRegs * activeThreads));
-
- //Initialize values
- for (int i=0; i < numLogicalIntRegs * activeThreads; i++) {
- regScoreBoard[i] = 1;
- }
-
- for (int i= numPhysicalIntRegs;
- i < numPhysicalIntRegs + (numLogicalFloatRegs * activeThreads);
- i++) {
- regScoreBoard[i] = 1;
- }
-
- for (int i = numPhysicalRegs;
- i < numPhysicalRegs + (numMiscRegs * activeThreads);
- i++) {
- regScoreBoard[i] = 1;
- }
-}
-
-std::string
-Scoreboard::name() const
-{
- return "cpu.scoreboard";
-}
-
-bool
-Scoreboard::getReg(PhysRegIndex phys_reg)
-{
- // Always ready if int or fp zero reg.
- if (phys_reg == zeroRegIdx ||
- phys_reg == (zeroRegIdx + numPhysicalIntRegs)) {
- return 1;
- }
-
- return regScoreBoard[phys_reg];
-}
-
-void
-Scoreboard::setReg(PhysRegIndex phys_reg)
-{
- DPRINTF(Scoreboard, "Setting reg %i as ready\n", phys_reg);
-
- regScoreBoard[phys_reg] = 1;
-}
-
-void
-Scoreboard::unsetReg(PhysRegIndex ready_reg)
-{
- if (ready_reg == zeroRegIdx ||
- ready_reg == (zeroRegIdx + numPhysicalIntRegs)) {
- // Don't do anything if int or fp zero reg.
- return;
- }
-
- regScoreBoard[ready_reg] = 0;
-}
diff --git a/cpu/o3/scoreboard.hh b/cpu/o3/scoreboard.hh
deleted file mode 100644
index 77f2cf157..000000000
--- a/cpu/o3/scoreboard.hh
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_SCOREBOARD_HH__
-#define __CPU_O3_SCOREBOARD_HH__
-
-#include <iostream>
-#include <utility>
-#include <vector>
-#include "arch/alpha/isa_traits.hh"
-#include "base/trace.hh"
-#include "base/traceflags.hh"
-#include "cpu/o3/comm.hh"
-
-/**
- * Implements a simple scoreboard to track which registers are ready.
- * This class assumes that the fp registers start, index wise, right after
- * the integer registers. The misc. registers start, index wise, right after
- * the fp registers.
- * @todo: Fix up handling of the zero register in case the decoder does not
- * automatically make insts that write the zero register into nops.
- */
-class Scoreboard
-{
- public:
- /** Constructs a scoreboard.
- * @param activeThreads The number of active threads.
- * @param _numLogicalIntRegs Number of logical integer registers.
- * @param _numPhysicalIntRegs Number of physical integer registers.
- * @param _numLogicalFloatRegs Number of logical fp registers.
- * @param _numPhysicalFloatRegs Number of physical fp registers.
- * @param _numMiscRegs Number of miscellaneous registers.
- * @param _zeroRegIdx Index of the zero register.
- */
- Scoreboard(unsigned activeThreads,
- unsigned _numLogicalIntRegs,
- unsigned _numPhysicalIntRegs,
- unsigned _numLogicalFloatRegs,
- unsigned _numPhysicalFloatRegs,
- unsigned _numMiscRegs,
- unsigned _zeroRegIdx);
-
- /** Destructor. */
- ~Scoreboard() {}
-
- /** Returns the name of the scoreboard. */
- std::string name() const;
-
- /** Checks if the register is ready. */
- bool getReg(PhysRegIndex ready_reg);
-
- /** Sets the register as ready. */
- void setReg(PhysRegIndex phys_reg);
-
- /** Sets the register as not ready. */
- void unsetReg(PhysRegIndex ready_reg);
-
- private:
- /** Scoreboard of physical integer registers, saying whether or not they
- * are ready.
- */
- std::vector<bool> regScoreBoard;
-
- /** Number of logical integer registers. */
- int numLogicalIntRegs;
-
- /** Number of physical integer registers. */
- int numPhysicalIntRegs;
-
- /** Number of logical floating point registers. */
- int numLogicalFloatRegs;
-
- /** Number of physical floating point registers. */
- int numPhysicalFloatRegs;
-
- /** Number of miscellaneous registers. */
- int numMiscRegs;
-
- /** Number of logical integer + float registers. */
- int numLogicalRegs;
-
- /** Number of physical integer + float registers. */
- int numPhysicalRegs;
-
- /** The logical index of the zero register. */
- int zeroRegIdx;
-};
-
-#endif
diff --git a/cpu/o3/store_set.cc b/cpu/o3/store_set.cc
deleted file mode 100644
index 67ccf1b55..000000000
--- a/cpu/o3/store_set.cc
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "base/intmath.hh"
-#include "base/trace.hh"
-#include "cpu/o3/store_set.hh"
-
-StoreSet::StoreSet(int _SSIT_size, int _LFST_size)
- : SSITSize(_SSIT_size), LFSTSize(_LFST_size)
-{
- DPRINTF(StoreSet, "StoreSet: Creating store set object.\n");
- DPRINTF(StoreSet, "StoreSet: SSIT size: %i, LFST size: %i.\n",
- SSITSize, LFSTSize);
-
- if (!isPowerOf2(SSITSize)) {
- fatal("Invalid SSIT size!\n");
- }
-
- SSIT.resize(SSITSize);
-
- validSSIT.resize(SSITSize);
-
- for (int i = 0; i < SSITSize; ++i)
- validSSIT[i] = false;
-
- if (!isPowerOf2(LFSTSize)) {
- fatal("Invalid LFST size!\n");
- }
-
- LFST.resize(LFSTSize);
-
- validLFST.resize(LFSTSize);
-
- for (int i = 0; i < LFSTSize; ++i) {
- validLFST[i] = false;
- LFST[i] = 0;
- }
-
- indexMask = SSITSize - 1;
-
- offsetBits = 2;
-}
-
-StoreSet::~StoreSet()
-{
-}
-
-void
-StoreSet::init(int _SSIT_size, int _LFST_size)
-{
- SSITSize = _SSIT_size;
- LFSTSize = _LFST_size;
-
- DPRINTF(StoreSet, "StoreSet: Creating store set object.\n");
- DPRINTF(StoreSet, "StoreSet: SSIT size: %i, LFST size: %i.\n",
- SSITSize, LFSTSize);
-
- SSIT.resize(SSITSize);
-
- validSSIT.resize(SSITSize);
-
- for (int i = 0; i < SSITSize; ++i)
- validSSIT[i] = false;
-
- LFST.resize(LFSTSize);
-
- validLFST.resize(LFSTSize);
-
- for (int i = 0; i < LFSTSize; ++i) {
- validLFST[i] = false;
- LFST[i] = 0;
- }
-
- indexMask = SSITSize - 1;
-
- offsetBits = 2;
-}
-
-
-void
-StoreSet::violation(Addr store_PC, Addr load_PC)
-{
- int load_index = calcIndex(load_PC);
- int store_index = calcIndex(store_PC);
-
- assert(load_index < SSITSize && store_index < SSITSize);
-
- bool valid_load_SSID = validSSIT[load_index];
- bool valid_store_SSID = validSSIT[store_index];
-
- if (!valid_load_SSID && !valid_store_SSID) {
- // Calculate a new SSID here.
- SSID new_set = calcSSID(load_PC);
-
- validSSIT[load_index] = true;
-
- SSIT[load_index] = new_set;
-
- validSSIT[store_index] = true;
-
- SSIT[store_index] = new_set;
-
- assert(new_set < LFSTSize);
-
- DPRINTF(StoreSet, "StoreSet: Neither load nor store had a valid "
- "storeset, creating a new one: %i for load %#x, store %#x\n",
- new_set, load_PC, store_PC);
- } else if (valid_load_SSID && !valid_store_SSID) {
- SSID load_SSID = SSIT[load_index];
-
- validSSIT[store_index] = true;
-
- SSIT[store_index] = load_SSID;
-
- assert(load_SSID < LFSTSize);
-
- DPRINTF(StoreSet, "StoreSet: Load had a valid store set. Adding "
- "store to that set: %i for load %#x, store %#x\n",
- load_SSID, load_PC, store_PC);
- } else if (!valid_load_SSID && valid_store_SSID) {
- SSID store_SSID = SSIT[store_index];
-
- validSSIT[load_index] = true;
-
- SSIT[load_index] = store_SSID;
-
- DPRINTF(StoreSet, "StoreSet: Store had a valid store set: %i for "
- "load %#x, store %#x\n",
- store_SSID, load_PC, store_PC);
- } else {
- SSID load_SSID = SSIT[load_index];
- SSID store_SSID = SSIT[store_index];
-
- assert(load_SSID < LFSTSize && store_SSID < LFSTSize);
-
- // The store set with the lower number wins
- if (store_SSID > load_SSID) {
- SSIT[store_index] = load_SSID;
-
- DPRINTF(StoreSet, "StoreSet: Load had smaller store set: %i; "
- "for load %#x, store %#x\n",
- load_SSID, load_PC, store_PC);
- } else {
- SSIT[load_index] = store_SSID;
-
- DPRINTF(StoreSet, "StoreSet: Store had smaller store set: %i; "
- "for load %#x, store %#x\n",
- store_SSID, load_PC, store_PC);
- }
- }
-}
-
-void
-StoreSet::insertLoad(Addr load_PC, InstSeqNum load_seq_num)
-{
- // Does nothing.
- return;
-}
-
-void
-StoreSet::insertStore(Addr store_PC, InstSeqNum store_seq_num,
- unsigned tid)
-{
- int index = calcIndex(store_PC);
-
- int store_SSID;
-
- assert(index < SSITSize);
-
- if (!validSSIT[index]) {
- // Do nothing if there's no valid entry.
- return;
- } else {
- store_SSID = SSIT[index];
-
- assert(store_SSID < LFSTSize);
-
- // Update the last store that was fetched with the current one.
- LFST[store_SSID] = store_seq_num;
-
- validLFST[store_SSID] = 1;
-
- storeList[store_seq_num] = store_SSID;
-
- DPRINTF(StoreSet, "Store %#x updated the LFST, SSID: %i\n",
- store_PC, store_SSID);
- }
-}
-
-InstSeqNum
-StoreSet::checkInst(Addr PC)
-{
- int index = calcIndex(PC);
-
- int inst_SSID;
-
- assert(index < SSITSize);
-
- if (!validSSIT[index]) {
- DPRINTF(StoreSet, "Inst %#x with index %i had no SSID\n",
- PC, index);
-
- // Return 0 if there's no valid entry.
- return 0;
- } else {
- inst_SSID = SSIT[index];
-
- assert(inst_SSID < LFSTSize);
-
- if (!validLFST[inst_SSID]) {
-
- DPRINTF(StoreSet, "Inst %#x with index %i and SSID %i had no "
- "dependency\n", PC, index, inst_SSID);
-
- return 0;
- } else {
- DPRINTF(StoreSet, "Inst %#x with index %i and SSID %i had LFST "
- "inum of %i\n", PC, index, inst_SSID, LFST[inst_SSID]);
-
- return LFST[inst_SSID];
- }
- }
-}
-
-void
-StoreSet::issued(Addr issued_PC, InstSeqNum issued_seq_num, bool is_store)
-{
- // This only is updated upon a store being issued.
- if (!is_store) {
- return;
- }
-
- int index = calcIndex(issued_PC);
-
- int store_SSID;
-
- assert(index < SSITSize);
-
- SeqNumMapIt store_list_it = storeList.find(issued_seq_num);
-
- if (store_list_it != storeList.end()) {
- storeList.erase(store_list_it);
- }
-
- // Make sure the SSIT still has a valid entry for the issued store.
- if (!validSSIT[index]) {
- return;
- }
-
- store_SSID = SSIT[index];
-
- assert(store_SSID < LFSTSize);
-
- // If the last fetched store in the store set refers to the store that
- // was just issued, then invalidate the entry.
- if (validLFST[store_SSID] && LFST[store_SSID] == issued_seq_num) {
- DPRINTF(StoreSet, "StoreSet: store invalidated itself in LFST.\n");
- validLFST[store_SSID] = false;
- }
-}
-
-void
-StoreSet::squash(InstSeqNum squashed_num, unsigned tid)
-{
- DPRINTF(StoreSet, "StoreSet: Squashing until inum %i\n",
- squashed_num);
-
- int idx;
- SeqNumMapIt store_list_it = storeList.begin();
-
- //@todo:Fix to only delete from correct thread
- while (!storeList.empty()) {
- idx = (*store_list_it).second;
-
- if ((*store_list_it).first <= squashed_num) {
- break;
- }
-
- bool younger = LFST[idx] > squashed_num;
-
- if (validLFST[idx] && younger) {
- DPRINTF(StoreSet, "Squashed [sn:%lli]\n", LFST[idx]);
- validLFST[idx] = false;
-
- storeList.erase(store_list_it++);
- } else if (!validLFST[idx] && younger) {
- storeList.erase(store_list_it++);
- }
- }
-}
-
-void
-StoreSet::clear()
-{
- for (int i = 0; i < SSITSize; ++i) {
- validSSIT[i] = false;
- }
-
- for (int i = 0; i < LFSTSize; ++i) {
- validLFST[i] = false;
- }
-
- storeList.clear();
-}
-
-void
-StoreSet::dump()
-{
- cprintf("storeList.size(): %i\n", storeList.size());
- SeqNumMapIt store_list_it = storeList.begin();
-
- int num = 0;
-
- while (store_list_it != storeList.end()) {
- cprintf("%i: [sn:%lli] SSID:%i\n",
- num, (*store_list_it).first, (*store_list_it).second);
- num++;
- store_list_it++;
- }
-}
diff --git a/cpu/o3/store_set.hh b/cpu/o3/store_set.hh
deleted file mode 100644
index 5f875131c..000000000
--- a/cpu/o3/store_set.hh
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_STORE_SET_HH__
-#define __CPU_O3_STORE_SET_HH__
-
-#include <list>
-#include <map>
-#include <utility>
-#include <vector>
-
-#include "arch/isa_traits.hh"
-#include "cpu/inst_seq.hh"
-
-struct ltseqnum {
- bool operator()(const InstSeqNum &lhs, const InstSeqNum &rhs) const
- {
- return lhs > rhs;
- }
-};
-
-/**
- * Implements a store set predictor for determining if memory
- * instructions are dependent upon each other. See paper "Memory
- * Dependence Prediction using Store Sets" by Chrysos and Emer. SSID
- * stands for Store Set ID, SSIT stands for Store Set ID Table, and
- * LFST is Last Fetched Store Table.
- */
-class StoreSet
-{
- public:
- typedef unsigned SSID;
-
- public:
- /** Default constructor. init() must be called prior to use. */
- StoreSet() { };
-
- /** Creates store set predictor with given table sizes. */
- StoreSet(int SSIT_size, int LFST_size);
-
- /** Default destructor. */
- ~StoreSet();
-
- /** Initializes the store set predictor with the given table sizes. */
- void init(int SSIT_size, int LFST_size);
-
- /** Records a memory ordering violation between the younger load
- * and the older store. */
- void violation(Addr store_PC, Addr load_PC);
-
- /** Inserts a load into the store set predictor. This does nothing but
- * is included in case other predictors require a similar function.
- */
- void insertLoad(Addr load_PC, InstSeqNum load_seq_num);
-
- /** Inserts a store into the store set predictor. Updates the
- * LFST if the store has a valid SSID. */
- void insertStore(Addr store_PC, InstSeqNum store_seq_num,
- unsigned tid);
-
- /** Checks if the instruction with the given PC is dependent upon
- * any store. @return Returns the sequence number of the store
- * instruction this PC is dependent upon. Returns 0 if none.
- */
- InstSeqNum checkInst(Addr PC);
-
- /** Records this PC/sequence number as issued. */
- void issued(Addr issued_PC, InstSeqNum issued_seq_num, bool is_store);
-
- /** Squashes for a specific thread until the given sequence number. */
- void squash(InstSeqNum squashed_num, unsigned tid);
-
- /** Resets all tables. */
- void clear();
-
- /** Debug function to dump the contents of the store list. */
- void dump();
-
- private:
- /** Calculates the index into the SSIT based on the PC. */
- inline int calcIndex(Addr PC)
- { return (PC >> offsetBits) & indexMask; }
-
- /** Calculates a Store Set ID based on the PC. */
- inline SSID calcSSID(Addr PC)
- { return ((PC ^ (PC >> 10)) % LFSTSize); }
-
- /** The Store Set ID Table. */
- std::vector<SSID> SSIT;
-
- /** Bit vector to tell if the SSIT has a valid entry. */
- std::vector<bool> validSSIT;
-
- /** Last Fetched Store Table. */
- std::vector<InstSeqNum> LFST;
-
- /** Bit vector to tell if the LFST has a valid entry. */
- std::vector<bool> validLFST;
-
- /** Map of stores that have been inserted into the store set, but
- * not yet issued or squashed.
- */
- std::map<InstSeqNum, int, ltseqnum> storeList;
-
- typedef std::map<InstSeqNum, int, ltseqnum>::iterator SeqNumMapIt;
-
- /** Store Set ID Table size, in entries. */
- int SSITSize;
-
- /** Last Fetched Store Table size, in entries. */
- int LFSTSize;
-
- /** Mask to obtain the index. */
- int indexMask;
-
- // HACK: Hardcoded for now.
- int offsetBits;
-};
-
-#endif // __CPU_O3_STORE_SET_HH__
diff --git a/cpu/o3/thread_state.hh b/cpu/o3/thread_state.hh
deleted file mode 100644
index 3f1208ea0..000000000
--- a/cpu/o3/thread_state.hh
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_THREAD_STATE_HH__
-#define __CPU_O3_THREAD_STATE_HH__
-
-#include "arch/faults.hh"
-#include "arch/isa_traits.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/thread_state.hh"
-
-class Event;
-class Process;
-
-#if FULL_SYSTEM
-class EndQuiesceEvent;
-class FunctionProfile;
-class ProfileNode;
-#else
-class FunctionalMemory;
-class Process;
-#endif
-
-/**
- * Class that has various thread state, such as the status, the
- * current instruction being processed, whether or not the thread has
- * a trap pending or is being externally updated, the ExecContext
- * proxy pointer, etc. It also handles anything related to a specific
- * thread's process, such as syscalls and checking valid addresses.
- */
-template <class Impl>
-struct O3ThreadState : public ThreadState {
- typedef ExecContext::Status Status;
- typedef typename Impl::FullCPU FullCPU;
-
- /** Current status of the thread. */
- Status _status;
-
- /** Current instruction the thread is committing. Only set and
- * used for DTB faults currently.
- */
- TheISA::MachInst inst;
-
- private:
- /** Pointer to the CPU. */
- FullCPU *cpu;
- public:
- /** Whether or not the thread is currently in syscall mode, and
- * thus able to be externally updated without squashing.
- */
- bool inSyscall;
-
- /** Whether or not the thread is currently waiting on a trap, and
- * thus able to be externally updated without squashing.
- */
- bool trapPending;
-
-#if FULL_SYSTEM
- O3ThreadState(FullCPU *_cpu, int _thread_num, FunctionalMemory *_mem)
- : ThreadState(-1, _thread_num, _mem),
- inSyscall(0), trapPending(0)
- { }
-#else
- O3ThreadState(FullCPU *_cpu, int _thread_num, Process *_process, int _asid)
- : ThreadState(-1, _thread_num, _process->getMemory(), _process, _asid),
- cpu(_cpu), inSyscall(0), trapPending(0)
- { }
-
- O3ThreadState(FullCPU *_cpu, int _thread_num, FunctionalMemory *_mem,
- int _asid)
- : ThreadState(-1, _thread_num, _mem, NULL, _asid),
- cpu(_cpu), inSyscall(0), trapPending(0)
- { }
-#endif
-
- /** Pointer to the ExecContext of this thread. @todo: Don't call
- this a proxy.*/
- ExecContext *xcProxy;
-
- /** Returns a pointer to the XC of this thread. */
- ExecContext *getXCProxy() { return xcProxy; }
-
- /** Returns the status of this thread. */
- Status status() const { return _status; }
-
- /** Sets the status of this thread. */
- void setStatus(Status new_status) { _status = new_status; }
-
-#if !FULL_SYSTEM
- /** Returns if this address is a valid instruction address. */
- bool validInstAddr(Addr addr)
- { return process->validInstAddr(addr); }
-
- /** Returns if this address is a valid data address. */
- bool validDataAddr(Addr addr)
- { return process->validDataAddr(addr); }
-#endif
-
- /** Sets the current instruction being committed. */
- void setInst(TheISA::MachInst _inst) { inst = _inst; }
-
- /** Reads the number of instructions functionally executed and
- * committed.
- */
- Counter readFuncExeInst() { return funcExeInst; }
-
- /** Sets the total number of instructions functionally executed
- * and committed.
- */
- void setFuncExeInst(Counter new_val) { funcExeInst = new_val; }
-
-#if !FULL_SYSTEM
- /** Handles the syscall. */
- void syscall() { process->syscall(xcProxy); }
-#endif
-};
-
-#endif // __CPU_O3_THREAD_STATE_HH__
diff --git a/cpu/o3/tournament_pred.cc b/cpu/o3/tournament_pred.cc
deleted file mode 100644
index f8c95abd8..000000000
--- a/cpu/o3/tournament_pred.cc
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "base/intmath.hh"
-#include "cpu/o3/tournament_pred.hh"
-
-TournamentBP::TournamentBP(unsigned _localPredictorSize,
- unsigned _localCtrBits,
- unsigned _localHistoryTableSize,
- unsigned _localHistoryBits,
- unsigned _globalPredictorSize,
- unsigned _globalCtrBits,
- unsigned _globalHistoryBits,
- unsigned _choicePredictorSize,
- unsigned _choiceCtrBits,
- unsigned _instShiftAmt)
- : localPredictorSize(_localPredictorSize),
- localCtrBits(_localCtrBits),
- localHistoryTableSize(_localHistoryTableSize),
- localHistoryBits(_localHistoryBits),
- globalPredictorSize(_globalPredictorSize),
- globalCtrBits(_globalCtrBits),
- globalHistoryBits(_globalHistoryBits),
- choicePredictorSize(_globalPredictorSize),
- choiceCtrBits(_choiceCtrBits),
- instShiftAmt(_instShiftAmt)
-{
- if (!isPowerOf2(localPredictorSize)) {
- fatal("Invalid local predictor size!\n");
- }
-
- //Setup the array of counters for the local predictor
- localCtrs.resize(localPredictorSize);
-
- for (int i = 0; i < localPredictorSize; ++i)
- localCtrs[i].setBits(localCtrBits);
-
- if (!isPowerOf2(localHistoryTableSize)) {
- fatal("Invalid local history table size!\n");
- }
-
- //Setup the history table for the local table
- localHistoryTable.resize(localHistoryTableSize);
-
- for (int i = 0; i < localHistoryTableSize; ++i)
- localHistoryTable[i] = 0;
-
- // Setup the local history mask
- localHistoryMask = (1 << localHistoryBits) - 1;
-
- if (!isPowerOf2(globalPredictorSize)) {
- fatal("Invalid global predictor size!\n");
- }
-
- //Setup the array of counters for the global predictor
- globalCtrs.resize(globalPredictorSize);
-
- for (int i = 0; i < globalPredictorSize; ++i)
- globalCtrs[i].setBits(globalCtrBits);
-
- //Clear the global history
- globalHistory = 0;
- // Setup the global history mask
- globalHistoryMask = (1 << globalHistoryBits) - 1;
-
- if (!isPowerOf2(choicePredictorSize)) {
- fatal("Invalid choice predictor size!\n");
- }
-
- //Setup the array of counters for the choice predictor
- choiceCtrs.resize(choicePredictorSize);
-
- for (int i = 0; i < choicePredictorSize; ++i)
- choiceCtrs[i].setBits(choiceCtrBits);
-
- // @todo: Allow for different thresholds between the predictors.
- threshold = (1 << (localCtrBits - 1)) - 1;
- threshold = threshold / 2;
-}
-
-inline
-unsigned
-TournamentBP::calcLocHistIdx(Addr &branch_addr)
-{
- // Get low order bits after removing instruction offset.
- return (branch_addr >> instShiftAmt) & (localHistoryTableSize - 1);
-}
-
-inline
-void
-TournamentBP::updateGlobalHistTaken()
-{
- globalHistory = (globalHistory << 1) | 1;
- globalHistory = globalHistory & globalHistoryMask;
-}
-
-inline
-void
-TournamentBP::updateGlobalHistNotTaken()
-{
- globalHistory = (globalHistory << 1);
- globalHistory = globalHistory & globalHistoryMask;
-}
-
-inline
-void
-TournamentBP::updateLocalHistTaken(unsigned local_history_idx)
-{
- localHistoryTable[local_history_idx] =
- (localHistoryTable[local_history_idx] << 1) | 1;
-}
-
-inline
-void
-TournamentBP::updateLocalHistNotTaken(unsigned local_history_idx)
-{
- localHistoryTable[local_history_idx] =
- (localHistoryTable[local_history_idx] << 1);
-}
-
-bool
-TournamentBP::lookup(Addr &branch_addr, void * &bp_history)
-{
- bool local_prediction;
- unsigned local_history_idx;
- unsigned local_predictor_idx;
-
- bool global_prediction;
- bool choice_prediction;
-
- //Lookup in the local predictor to get its branch prediction
- local_history_idx = calcLocHistIdx(branch_addr);
- local_predictor_idx = localHistoryTable[local_history_idx]
- & localHistoryMask;
- local_prediction = localCtrs[local_predictor_idx].read() > threshold;
-
- //Lookup in the global predictor to get its branch prediction
- global_prediction = globalCtrs[globalHistory].read() > threshold;
-
- //Lookup in the choice predictor to see which one to use
- choice_prediction = choiceCtrs[globalHistory].read() > threshold;
-
- // Create BPHistory and pass it back to be recorded.
- BPHistory *history = new BPHistory;
- history->globalHistory = globalHistory;
- history->localPredTaken = local_prediction;
- history->globalPredTaken = global_prediction;
- history->globalUsed = choice_prediction;
- bp_history = (void *)history;
-
- assert(globalHistory < globalPredictorSize &&
- local_history_idx < localPredictorSize);
-
- // Commented code is for doing speculative update of counters and
- // all histories.
- if (choice_prediction) {
- if (global_prediction) {
-// updateHistoriesTaken(local_history_idx);
-// globalCtrs[globalHistory].increment();
-// localCtrs[local_history_idx].increment();
- updateGlobalHistTaken();
- return true;
- } else {
-// updateHistoriesNotTaken(local_history_idx);
-// globalCtrs[globalHistory].decrement();
-// localCtrs[local_history_idx].decrement();
- updateGlobalHistNotTaken();
- return false;
- }
- } else {
- if (local_prediction) {
-// updateHistoriesTaken(local_history_idx);
-// globalCtrs[globalHistory].increment();
-// localCtrs[local_history_idx].increment();
- updateGlobalHistTaken();
- return true;
- } else {
-// updateHistoriesNotTaken(local_history_idx);
-// globalCtrs[globalHistory].decrement();
-// localCtrs[local_history_idx].decrement();
- updateGlobalHistNotTaken();
- return false;
- }
- }
-}
-
-void
-TournamentBP::uncondBr(void * &bp_history)
-{
- // Create BPHistory and pass it back to be recorded.
- BPHistory *history = new BPHistory;
- history->globalHistory = globalHistory;
- history->localPredTaken = true;
- history->globalPredTaken = true;
- bp_history = static_cast<void *>(history);
-
- updateGlobalHistTaken();
-}
-
-void
-TournamentBP::update(Addr &branch_addr, bool taken, void *bp_history)
-{
- unsigned local_history_idx;
- unsigned local_predictor_idx;
- unsigned local_predictor_hist;
-
- // Get the local predictor's current prediction
- local_history_idx = calcLocHistIdx(branch_addr);
- local_predictor_hist = localHistoryTable[local_history_idx];
- local_predictor_idx = local_predictor_hist & localHistoryMask;
-
- // Update the choice predictor to tell it which one was correct if
- // there was a prediction.
- if (bp_history) {
- BPHistory *history = static_cast<BPHistory *>(bp_history);
- if (history->localPredTaken != history->globalPredTaken) {
- // If the local prediction matches the actual outcome,
- // decerement the counter. Otherwise increment the
- // counter.
- if (history->localPredTaken == taken) {
- choiceCtrs[globalHistory].decrement();
- } else if (history->globalPredTaken == taken){
- choiceCtrs[globalHistory].increment();
- }
- }
-
- // We're done with this history, now delete it.
- delete history;
- }
-
- assert(globalHistory < globalPredictorSize &&
- local_predictor_idx < localPredictorSize);
-
- // Update the counters and local history with the proper
- // resolution of the branch. Global history is updated
- // speculatively and restored upon squash() calls, so it does not
- // need to be updated.
- if (taken) {
- localCtrs[local_predictor_idx].increment();
- globalCtrs[globalHistory].increment();
-
- updateLocalHistTaken(local_history_idx);
- } else {
- localCtrs[local_predictor_idx].decrement();
- globalCtrs[globalHistory].decrement();
-
- updateLocalHistNotTaken(local_history_idx);
- }
-}
-
-void
-TournamentBP::squash(void *bp_history)
-{
- BPHistory *history = static_cast<BPHistory *>(bp_history);
-
- // Restore global history to state prior to this branch.
- globalHistory = history->globalHistory;
-
- // Delete this BPHistory now that we're done with it.
- delete history;
-}
-
-#ifdef DEBUG
-int
-TournamentBP::BPHistory::newCount = 0;
-#endif
diff --git a/cpu/o3/tournament_pred.hh b/cpu/o3/tournament_pred.hh
deleted file mode 100644
index 6d77999cc..000000000
--- a/cpu/o3/tournament_pred.hh
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_TOURNAMENT_PRED_HH__
-#define __CPU_O3_TOURNAMENT_PRED_HH__
-
-// For Addr type.
-#include "arch/isa_traits.hh"
-#include "cpu/o3/sat_counter.hh"
-#include <vector>
-
-/**
- * Implements a tournament branch predictor, hopefully identical to the one
- * used in the 21264. It has a local predictor, which uses a local history
- * table to index into a table of counters, and a global predictor, which
- * uses a global history to index into a table of counters. A choice
- * predictor chooses between the two. Only the global history register
- * is speculatively updated, the rest are updated upon branches committing
- * or misspeculating.
- */
-class TournamentBP
-{
- public:
- /**
- * Default branch predictor constructor.
- */
- TournamentBP(unsigned localPredictorSize,
- unsigned localCtrBits,
- unsigned localHistoryTableSize,
- unsigned localHistoryBits,
- unsigned globalPredictorSize,
- unsigned globalHistoryBits,
- unsigned globalCtrBits,
- unsigned choicePredictorSize,
- unsigned choiceCtrBits,
- unsigned instShiftAmt);
-
- /**
- * Looks up the given address in the branch predictor and returns
- * a true/false value as to whether it is taken. Also creates a
- * BPHistory object to store any state it will need on squash/update.
- * @param branch_addr The address of the branch to look up.
- * @param bp_history Pointer that will be set to the BPHistory object.
- * @return Whether or not the branch is taken.
- */
- bool lookup(Addr &branch_addr, void * &bp_history);
-
- /**
- * Records that there was an unconditional branch, and modifies
- * the bp history to point to an object that has the previous
- * global history stored in it.
- * @param bp_history Pointer that will be set to the BPHistory object.
- */
- void uncondBr(void * &bp_history);
-
- /**
- * Updates the branch predictor with the actual result of a branch.
- * @param branch_addr The address of the branch to update.
- * @param taken Whether or not the branch was taken.
- * @param bp_history Pointer to the BPHistory object that was created
- * when the branch was predicted.
- */
- void update(Addr &branch_addr, bool taken, void *bp_history);
-
- /**
- * Restores the global branch history on a squash.
- * @param bp_history Pointer to the BPHistory object that has the
- * previous global branch history in it.
- */
- void squash(void *bp_history);
-
- /** Returns the global history. */
- inline unsigned readGlobalHist() { return globalHistory; }
-
- private:
- /**
- * Returns if the branch should be taken or not, given a counter
- * value.
- * @param count The counter value.
- */
- inline bool getPrediction(uint8_t &count);
-
- /**
- * Returns the local history index, given a branch address.
- * @param branch_addr The branch's PC address.
- */
- inline unsigned calcLocHistIdx(Addr &branch_addr);
-
- /** Updates global history as taken. */
- inline void updateGlobalHistTaken();
-
- /** Updates global history as not taken. */
- inline void updateGlobalHistNotTaken();
-
- /**
- * Updates local histories as taken.
- * @param local_history_idx The local history table entry that
- * will be updated.
- */
- inline void updateLocalHistTaken(unsigned local_history_idx);
-
- /**
- * Updates local histories as not taken.
- * @param local_history_idx The local history table entry that
- * will be updated.
- */
- inline void updateLocalHistNotTaken(unsigned local_history_idx);
-
- /**
- * The branch history information that is created upon predicting
- * a branch. It will be passed back upon updating and squashing,
- * when the BP can use this information to update/restore its
- * state properly.
- */
- struct BPHistory {
-#ifdef DEBUG
- BPHistory()
- { newCount++; }
- ~BPHistory()
- { newCount--; }
-
- static int newCount;
-#endif
- unsigned globalHistory;
- bool localPredTaken;
- bool globalPredTaken;
- bool globalUsed;
- };
-
- /** Local counters. */
- std::vector<SatCounter> localCtrs;
-
- /** Size of the local predictor. */
- unsigned localPredictorSize;
-
- /** Number of bits of the local predictor's counters. */
- unsigned localCtrBits;
-
- /** Array of local history table entries. */
- std::vector<unsigned> localHistoryTable;
-
- /** Size of the local history table. */
- unsigned localHistoryTableSize;
-
- /** Number of bits for each entry of the local history table.
- * @todo Doesn't this come from the size of the local predictor?
- */
- unsigned localHistoryBits;
-
- /** Mask to get the proper local history. */
- unsigned localHistoryMask;
-
- /** Array of counters that make up the global predictor. */
- std::vector<SatCounter> globalCtrs;
-
- /** Size of the global predictor. */
- unsigned globalPredictorSize;
-
- /** Number of bits of the global predictor's counters. */
- unsigned globalCtrBits;
-
- /** Global history register. */
- unsigned globalHistory;
-
- /** Number of bits for the global history. */
- unsigned globalHistoryBits;
-
- /** Mask to get the proper global history. */
- unsigned globalHistoryMask;
-
- /** Array of counters that make up the choice predictor. */
- std::vector<SatCounter> choiceCtrs;
-
- /** Size of the choice predictor (identical to the global predictor). */
- unsigned choicePredictorSize;
-
- /** Number of bits of the choice predictor's counters. */
- unsigned choiceCtrBits;
-
- /** Number of bits to shift the instruction over to get rid of the word
- * offset.
- */
- unsigned instShiftAmt;
-
- /** Threshold for the counter value; above the threshold is taken,
- * equal to or below the threshold is not taken.
- */
- unsigned threshold;
-};
-
-#endif // __CPU_O3_TOURNAMENT_PRED_HH__
diff --git a/cpu/ozone/back_end.cc b/cpu/ozone/back_end.cc
deleted file mode 100644
index cb014e4cc..000000000
--- a/cpu/ozone/back_end.cc
+++ /dev/null
@@ -1,5 +0,0 @@
-
-#include "cpu/ozone/back_end_impl.hh"
-#include "cpu/ozone/ozone_impl.hh"
-
-//template class BackEnd<OzoneImpl>;
diff --git a/cpu/ozone/back_end.hh b/cpu/ozone/back_end.hh
deleted file mode 100644
index 14b011ab8..000000000
--- a/cpu/ozone/back_end.hh
+++ /dev/null
@@ -1,516 +0,0 @@
-
-#ifndef __CPU_OZONE_BACK_END_HH__
-#define __CPU_OZONE_BACK_END_HH__
-
-#include <list>
-#include <queue>
-#include <string>
-
-#include "arch/faults.hh"
-#include "base/timebuf.hh"
-#include "cpu/inst_seq.hh"
-#include "cpu/ozone/rename_table.hh"
-#include "cpu/ozone/thread_state.hh"
-#include "mem/functional/functional.hh"
-#include "mem/mem_interface.hh"
-#include "mem/mem_req.hh"
-#include "sim/eventq.hh"
-
-class ExecContext;
-
-template <class Impl>
-class OzoneThreadState;
-
-template <class Impl>
-class BackEnd
-{
- public:
- typedef OzoneThreadState<Impl> Thread;
-
- typedef typename Impl::Params Params;
- typedef typename Impl::DynInst DynInst;
- typedef typename Impl::DynInstPtr DynInstPtr;
- typedef typename Impl::FullCPU FullCPU;
- typedef typename Impl::FrontEnd FrontEnd;
- typedef typename Impl::FullCPU::CommStruct CommStruct;
-
- struct SizeStruct {
- int size;
- };
-
- typedef SizeStruct DispatchToIssue;
- typedef SizeStruct IssueToExec;
- typedef SizeStruct ExecToCommit;
- typedef SizeStruct Writeback;
-
- TimeBuffer<DispatchToIssue> d2i;
- typename TimeBuffer<DispatchToIssue>::wire instsToDispatch;
- TimeBuffer<IssueToExec> i2e;
- typename TimeBuffer<IssueToExec>::wire instsToExecute;
- TimeBuffer<ExecToCommit> e2c;
- TimeBuffer<Writeback> numInstsToWB;
-
- TimeBuffer<CommStruct> *comm;
- typename TimeBuffer<CommStruct>::wire toIEW;
- typename TimeBuffer<CommStruct>::wire fromCommit;
-
- class InstQueue {
- enum queue {
- NonSpec,
- IQ,
- ToBeScheduled,
- ReadyList,
- ReplayList
- };
- struct pqCompare {
- bool operator() (const DynInstPtr &lhs, const DynInstPtr &rhs) const
- {
- return lhs->seqNum > rhs->seqNum;
- }
- };
- public:
- InstQueue(Params *params);
-
- std::string name() const;
-
- void regStats();
-
- void setIssueExecQueue(TimeBuffer<IssueToExec> *i2e_queue);
-
- void setBE(BackEnd *_be) { be = _be; }
-
- void insert(DynInstPtr &inst);
-
- void scheduleReadyInsts();
-
- void scheduleNonSpec(const InstSeqNum &sn);
-
- DynInstPtr getReadyInst();
-
- void commit(const InstSeqNum &sn) {}
-
- void squash(const InstSeqNum &sn);
-
- int wakeDependents(DynInstPtr &inst);
-
- /** Tells memory dependence unit that a memory instruction needs to be
- * rescheduled. It will re-execute once replayMemInst() is called.
- */
- void rescheduleMemInst(DynInstPtr &inst);
-
- /** Re-executes all rescheduled memory instructions. */
- void replayMemInst(DynInstPtr &inst);
-
- /** Completes memory instruction. */
- void completeMemInst(DynInstPtr &inst);
-
- void violation(DynInstPtr &inst, DynInstPtr &violation) { }
-
- bool isFull() { return numInsts >= size; }
-
- void dumpInsts();
-
- private:
- bool find(queue q, typename std::list<DynInstPtr>::iterator it);
- BackEnd *be;
- TimeBuffer<IssueToExec> *i2e;
- typename TimeBuffer<IssueToExec>::wire numIssued;
- typedef typename std::list<DynInstPtr> InstList;
- typedef typename std::list<DynInstPtr>::iterator InstListIt;
- typedef typename std::priority_queue<DynInstPtr, std::vector<DynInstPtr>, pqCompare> ReadyInstQueue;
- // Not sure I need the IQ list; it just needs to be a count.
- InstList iq;
- InstList toBeScheduled;
- InstList readyList;
- InstList nonSpec;
- InstList replayList;
- ReadyInstQueue readyQueue;
- public:
- int size;
- int numInsts;
- int width;
-
- Stats::VectorDistribution<> occ_dist;
-
- Stats::Vector<> inst_count;
- Stats::Vector<> peak_inst_count;
- Stats::Scalar<> empty_count;
- Stats::Scalar<> current_count;
- Stats::Scalar<> fullCount;
-
- Stats::Formula occ_rate;
- Stats::Formula avg_residency;
- Stats::Formula empty_rate;
- Stats::Formula full_rate;
- };
-
- /** LdWriteback event for a load completion. */
- class LdWritebackEvent : public Event {
- private:
- /** Instruction that is writing back data to the register file. */
- DynInstPtr inst;
- /** Pointer to IEW stage. */
- BackEnd *be;
-
- public:
- /** Constructs a load writeback event. */
- LdWritebackEvent(DynInstPtr &_inst, BackEnd *be);
-
- /** Processes writeback event. */
- virtual void process();
- /** Returns the description of the writeback event. */
- virtual const char *description();
- };
-
- BackEnd(Params *params);
-
- std::string name() const;
-
- void regStats();
-
- void setCPU(FullCPU *cpu_ptr)
- { cpu = cpu_ptr; }
-
- void setFrontEnd(FrontEnd *front_end_ptr)
- { frontEnd = front_end_ptr; }
-
- void setXC(ExecContext *xc_ptr)
- { xc = xc_ptr; }
-
- void setThreadState(Thread *thread_ptr)
- { thread = thread_ptr; }
-
- void setCommBuffer(TimeBuffer<CommStruct> *_comm);
-
- void tick();
- void squash();
- void squashFromXC();
- bool xcSquash;
-
- template <class T>
- Fault read(MemReqPtr &req, T &data, int load_idx);
-
- template <class T>
- Fault write(MemReqPtr &req, T &data, int store_idx);
-
- Addr readCommitPC() { return commitPC; }
-
- Addr commitPC;
-
- bool robEmpty() { return instList.empty(); }
-
- bool isFull() { return numInsts >= numROBEntries; }
- bool isBlocked() { return status == Blocked || dispatchStatus == Blocked; }
-
- /** Tells memory dependence unit that a memory instruction needs to be
- * rescheduled. It will re-execute once replayMemInst() is called.
- */
- void rescheduleMemInst(DynInstPtr &inst)
- { IQ.rescheduleMemInst(inst); }
-
- /** Re-executes all rescheduled memory instructions. */
- void replayMemInst(DynInstPtr &inst)
- { IQ.replayMemInst(inst); }
-
- /** Completes memory instruction. */
- void completeMemInst(DynInstPtr &inst)
- { IQ.completeMemInst(inst); }
-
- void fetchFault(Fault &fault);
-
- private:
- void updateStructures();
- void dispatchInsts();
- void dispatchStall();
- void checkDispatchStatus();
- void scheduleReadyInsts();
- void executeInsts();
- void commitInsts();
- void addToIQ(DynInstPtr &inst);
- void addToLSQ(DynInstPtr &inst);
- void instToCommit(DynInstPtr &inst);
- void writebackInsts();
- bool commitInst(int inst_num);
- void squash(const InstSeqNum &sn);
- void squashDueToBranch(DynInstPtr &inst);
- void squashDueToMemBlocked(DynInstPtr &inst);
- void updateExeInstStats(DynInstPtr &inst);
- void updateComInstStats(DynInstPtr &inst);
-
- public:
- FullCPU *cpu;
-
- FrontEnd *frontEnd;
-
- ExecContext *xc;
-
- Thread *thread;
-
- enum Status {
- Running,
- Idle,
- DcacheMissStall,
- DcacheMissComplete,
- Blocked
- };
-
- Status status;
-
- Status dispatchStatus;
-
- Counter funcExeInst;
-
- private:
-// typedef typename Impl::InstQueue InstQueue;
-
- InstQueue IQ;
-
- typedef typename Impl::LdstQueue LdstQueue;
-
- LdstQueue LSQ;
- public:
- RenameTable<Impl> commitRenameTable;
-
- RenameTable<Impl> renameTable;
- private:
- class DCacheCompletionEvent : public Event
- {
- private:
- BackEnd *be;
-
- public:
- DCacheCompletionEvent(BackEnd *_be);
-
- virtual void process();
- virtual const char *description();
- };
-
- friend class DCacheCompletionEvent;
-
- DCacheCompletionEvent cacheCompletionEvent;
-
- MemInterface *dcacheInterface;
-
- MemReqPtr memReq;
-
- // General back end width. Used if the more specific isn't given.
- int width;
-
- // Dispatch width.
- int dispatchWidth;
- int numDispatchEntries;
- int dispatchSize;
-
- int issueWidth;
-
- // Writeback width
- int wbWidth;
-
- // Commit width
- int commitWidth;
-
- /** Index into queue of instructions being written back. */
- unsigned wbNumInst;
-
- /** Cycle number within the queue of instructions being written
- * back. Used in case there are too many instructions writing
- * back at the current cycle and writesbacks need to be scheduled
- * for the future. See comments in instToCommit().
- */
- unsigned wbCycle;
-
- int numROBEntries;
- int numInsts;
-
- bool squashPending;
- InstSeqNum squashSeqNum;
- Addr squashNextPC;
-
- Fault faultFromFetch;
-
- private:
- typedef typename std::list<DynInstPtr>::iterator InstListIt;
-
- std::list<DynInstPtr> instList;
- std::list<DynInstPtr> dispatch;
- std::list<DynInstPtr> writeback;
-
- int latency;
-
- int squashLatency;
-
- bool exactFullStall;
-
- bool fetchRedirect[Impl::MaxThreads];
-
- // number of cycles stalled for D-cache misses
-/* Stats::Scalar<> dcacheStallCycles;
- Counter lastDcacheStall;
-*/
- Stats::Vector<> rob_cap_events;
- Stats::Vector<> rob_cap_inst_count;
- Stats::Vector<> iq_cap_events;
- Stats::Vector<> iq_cap_inst_count;
- // total number of instructions executed
- Stats::Vector<> exe_inst;
- Stats::Vector<> exe_swp;
- Stats::Vector<> exe_nop;
- Stats::Vector<> exe_refs;
- Stats::Vector<> exe_loads;
- Stats::Vector<> exe_branches;
-
- Stats::Vector<> issued_ops;
-
- // total number of loads forwaded from LSQ stores
- Stats::Vector<> lsq_forw_loads;
-
- // total number of loads ignored due to invalid addresses
- Stats::Vector<> inv_addr_loads;
-
- // total number of software prefetches ignored due to invalid addresses
- Stats::Vector<> inv_addr_swpfs;
- // ready loads blocked due to memory disambiguation
- Stats::Vector<> lsq_blocked_loads;
-
- Stats::Scalar<> lsqInversion;
-
- Stats::Vector<> n_issued_dist;
- Stats::VectorDistribution<> issue_delay_dist;
-
- Stats::VectorDistribution<> queue_res_dist;
-/*
- Stats::Vector<> stat_fu_busy;
- Stats::Vector2d<> stat_fuBusy;
- Stats::Vector<> dist_unissued;
- Stats::Vector2d<> stat_issued_inst_type;
-
- Stats::Formula misspec_cnt;
- Stats::Formula misspec_ipc;
- Stats::Formula issue_rate;
- Stats::Formula issue_stores;
- Stats::Formula issue_op_rate;
- Stats::Formula fu_busy_rate;
- Stats::Formula commit_stores;
- Stats::Formula commit_ipc;
- Stats::Formula commit_ipb;
- Stats::Formula lsq_inv_rate;
-*/
- Stats::Vector<> writeback_count;
- Stats::Vector<> producer_inst;
- Stats::Vector<> consumer_inst;
- Stats::Vector<> wb_penalized;
-
- Stats::Formula wb_rate;
- Stats::Formula wb_fanout;
- Stats::Formula wb_penalized_rate;
-
- // total number of instructions committed
- Stats::Vector<> stat_com_inst;
- Stats::Vector<> stat_com_swp;
- Stats::Vector<> stat_com_refs;
- Stats::Vector<> stat_com_loads;
- Stats::Vector<> stat_com_membars;
- Stats::Vector<> stat_com_branches;
-
- Stats::Distribution<> n_committed_dist;
-
- Stats::Scalar<> commit_eligible_samples;
- Stats::Vector<> commit_eligible;
-
- Stats::Scalar<> ROB_fcount;
- Stats::Formula ROB_full_rate;
-
- Stats::Vector<> ROB_count; // cumulative ROB occupancy
- Stats::Formula ROB_occ_rate;
- Stats::VectorDistribution<> ROB_occ_dist;
- public:
- void dumpInsts();
-};
-
-template <class Impl>
-template <class T>
-Fault
-BackEnd<Impl>::read(MemReqPtr &req, T &data, int load_idx)
-{
-/* memReq->reset(addr, sizeof(T), flags);
-
- // translate to physical address
- Fault fault = cpu->translateDataReadReq(memReq);
-
- // if we have a cache, do cache access too
- if (fault == NoFault && dcacheInterface) {
- memReq->cmd = Read;
- memReq->completionEvent = NULL;
- memReq->time = curTick;
- memReq->flags &= ~INST_READ;
- MemAccessResult result = dcacheInterface->access(memReq);
-
- // Ugly hack to get an event scheduled *only* if the access is
- // a miss. We really should add first-class support for this
- // at some point.
- if (result != MA_HIT && dcacheInterface->doEvents()) {
- // Fix this hack for keeping funcExeInst correct with loads that
- // are executed twice.
- --funcExeInst;
-
- memReq->completionEvent = &cacheCompletionEvent;
- lastDcacheStall = curTick;
-// unscheduleTickEvent();
-// status = DcacheMissStall;
- DPRINTF(OzoneCPU, "Dcache miss stall!\n");
- } else {
- // do functional access
- fault = thread->mem->read(memReq, data);
-
- }
- }
-*/
-/*
- if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
- recordEvent("Uncached Read");
-*/
- return LSQ.read(req, data, load_idx);
-}
-
-template <class Impl>
-template <class T>
-Fault
-BackEnd<Impl>::write(MemReqPtr &req, T &data, int store_idx)
-{
-/*
- memReq->reset(addr, sizeof(T), flags);
-
- // translate to physical address
- Fault fault = cpu->translateDataWriteReq(memReq);
-
- if (fault == NoFault && dcacheInterface) {
- memReq->cmd = Write;
- memcpy(memReq->data,(uint8_t *)&data,memReq->size);
- memReq->completionEvent = NULL;
- memReq->time = curTick;
- memReq->flags &= ~INST_READ;
- MemAccessResult result = dcacheInterface->access(memReq);
-
- // Ugly hack to get an event scheduled *only* if the access is
- // a miss. We really should add first-class support for this
- // at some point.
- if (result != MA_HIT && dcacheInterface->doEvents()) {
- memReq->completionEvent = &cacheCompletionEvent;
- lastDcacheStall = curTick;
-// unscheduleTickEvent();
-// status = DcacheMissStall;
- DPRINTF(OzoneCPU, "Dcache miss stall!\n");
- }
- }
-
- if (res && (fault == NoFault))
- *res = memReq->result;
- */
-/*
- if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
- recordEvent("Uncached Write");
-*/
- return LSQ.write(req, data, store_idx);
-}
-
-#endif // __CPU_OZONE_BACK_END_HH__
diff --git a/cpu/ozone/back_end_impl.hh b/cpu/ozone/back_end_impl.hh
deleted file mode 100644
index 36770d65c..000000000
--- a/cpu/ozone/back_end_impl.hh
+++ /dev/null
@@ -1,1904 +0,0 @@
-
-#include "encumbered/cpu/full/op_class.hh"
-#include "cpu/ozone/back_end.hh"
-
-template <class Impl>
-BackEnd<Impl>::InstQueue::InstQueue(Params *params)
- : size(params->numIQEntries), numInsts(0), width(params->issueWidth)
-{
-}
-
-template <class Impl>
-std::string
-BackEnd<Impl>::InstQueue::name() const
-{
- return be->name() + ".iq";
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::InstQueue::regStats()
-{
- using namespace Stats;
-
- occ_dist
- .init(1, 0, size, 2)
- .name(name() + "occ_dist")
- .desc("IQ Occupancy per cycle")
- .flags(total | cdf)
- ;
-
- inst_count
- .init(1)
- .name(name() + "cum_num_insts")
- .desc("Total occupancy")
- .flags(total)
- ;
-
- peak_inst_count
- .init(1)
- .name(name() + "peak_occupancy")
- .desc("Peak IQ occupancy")
- .flags(total)
- ;
-
- current_count
- .name(name() + "current_count")
- .desc("Occupancy this cycle")
- ;
-
- empty_count
- .name(name() + "empty_count")
- .desc("Number of empty cycles")
- ;
-
- fullCount
- .name(name() + "full_count")
- .desc("Number of full cycles")
- ;
-
-
- occ_rate
- .name(name() + "occ_rate")
- .desc("Average occupancy")
- .flags(total)
- ;
- occ_rate = inst_count / be->cpu->numCycles;
-
- avg_residency
- .name(name() + "avg_residency")
- .desc("Average IQ residency")
- .flags(total)
- ;
- avg_residency = occ_rate / be->cpu->numCycles;
-
- empty_rate
- .name(name() + "empty_rate")
- .desc("Fraction of cycles empty")
- ;
- empty_rate = 100 * empty_count / be->cpu->numCycles;
-
- full_rate
- .name(name() + "full_rate")
- .desc("Fraction of cycles full")
- ;
- full_rate = 100 * fullCount / be->cpu->numCycles;
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::InstQueue::setIssueExecQueue(TimeBuffer<IssueToExec> *i2e_queue)
-{
- i2e = i2e_queue;
- numIssued = i2e->getWire(0);
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::InstQueue::insert(DynInstPtr &inst)
-{
- numInsts++;
- inst_count[0]++;
- if (!inst->isNonSpeculative()) {
- DPRINTF(BE, "Instruction [sn:%lli] added to IQ\n", inst->seqNum);
- if (inst->readyToIssue()) {
- toBeScheduled.push_front(inst);
- inst->iqIt = toBeScheduled.begin();
- inst->iqItValid = true;
- } else {
- iq.push_front(inst);
- inst->iqIt = iq.begin();
- inst->iqItValid = true;
- }
- } else {
- DPRINTF(BE, "Nonspeculative instruction [sn:%lli] added to IQ\n", inst->seqNum);
- nonSpec.push_front(inst);
- inst->iqIt = nonSpec.begin();
- inst->iqItValid = true;
- }
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::InstQueue::scheduleReadyInsts()
-{
- int scheduled = numIssued->size;
- InstListIt iq_it = --toBeScheduled.end();
- InstListIt iq_end_it = toBeScheduled.end();
-
- while (iq_it != iq_end_it && scheduled < width) {
-// if ((*iq_it)->readyToIssue()) {
- DPRINTF(BE, "Instruction [sn:%lli] PC:%#x is ready\n",
- (*iq_it)->seqNum, (*iq_it)->readPC());
- readyQueue.push(*iq_it);
- readyList.push_front(*iq_it);
-
- (*iq_it)->iqIt = readyList.begin();
-
- toBeScheduled.erase(iq_it--);
-
- ++scheduled;
-// } else {
-// iq_it++;
-// }
- }
-
- numIssued->size+= scheduled;
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::InstQueue::scheduleNonSpec(const InstSeqNum &sn)
-{
-/*
- InstListIt non_spec_it = nonSpec.begin();
- InstListIt non_spec_end_it = nonSpec.end();
-
- while ((*non_spec_it)->seqNum != sn) {
- non_spec_it++;
- assert(non_spec_it != non_spec_end_it);
- }
-*/
- DynInstPtr inst = nonSpec.back();
-
- DPRINTF(BE, "Nonspeculative instruction [sn:%lli] scheduled\n", inst->seqNum);
-
- assert(inst->seqNum == sn);
-
- assert(find(NonSpec, inst->iqIt));
- nonSpec.erase(inst->iqIt);
- readyList.push_front(inst);
- inst->iqIt = readyList.begin();
- readyQueue.push(inst);
- numIssued->size++;
-}
-
-template <class Impl>
-typename Impl::DynInstPtr
-BackEnd<Impl>::InstQueue::getReadyInst()
-{
- assert(!readyList.empty());
-
- DynInstPtr inst = readyQueue.top();
- readyQueue.pop();
- assert(find(ReadyList, inst->iqIt));
- readyList.erase(inst->iqIt);
- inst->iqItValid = false;
-// if (!inst->isMemRef())
- --numInsts;
- return inst;
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::InstQueue::squash(const InstSeqNum &sn)
-{
- InstListIt iq_it = iq.begin();
- InstListIt iq_end_it = iq.end();
-
- while (iq_it != iq_end_it && (*iq_it)->seqNum > sn) {
- DPRINTF(BE, "Instruction [sn:%lli] removed from IQ\n", (*iq_it)->seqNum);
- (*iq_it)->iqItValid = false;
- iq.erase(iq_it++);
- --numInsts;
- }
-
- iq_it = nonSpec.begin();
- iq_end_it = nonSpec.end();
-
- while (iq_it != iq_end_it && (*iq_it)->seqNum > sn) {
- DPRINTF(BE, "Instruction [sn:%lli] removed from IQ\n", (*iq_it)->seqNum);
- (*iq_it)->iqItValid = false;
- nonSpec.erase(iq_it++);
- --numInsts;
- }
-
- iq_it = replayList.begin();
- iq_end_it = replayList.end();
-
- while (iq_it != iq_end_it) {
- if ((*iq_it)->seqNum > sn) {
- DPRINTF(BE, "Instruction [sn:%lli] removed from IQ\n", (*iq_it)->seqNum);
- (*iq_it)->iqItValid = false;
- replayList.erase(iq_it++);
- --numInsts;
- } else {
- iq_it++;
- }
- }
-
- assert(numInsts >= 0);
-/*
- InstListIt ready_it = readyList.begin();
- InstListIt ready_end_it = readyList.end();
-
- while (ready_it != ready_end_it) {
- if ((*ready_it)->seqNum > sn) {
- readyList.erase(ready_it++);
- } else {
- ready_it++;
- }
- }
-*/
-}
-
-template <class Impl>
-int
-BackEnd<Impl>::InstQueue::wakeDependents(DynInstPtr &inst)
-{
- assert(!inst->isSquashed());
- std::vector<DynInstPtr> &dependents = inst->getDependents();
- int num_outputs = dependents.size();
-
- DPRINTF(BE, "Waking instruction [sn:%lli] dependents in IQ\n", inst->seqNum);
-
- for (int i = 0; i < num_outputs; i++) {
- DynInstPtr dep_inst = dependents[i];
- dep_inst->markSrcRegReady();
- DPRINTF(BE, "Marking source reg ready [sn:%lli] in IQ\n", dep_inst->seqNum);
-
- if (dep_inst->readyToIssue() && dep_inst->iqItValid) {
- if (dep_inst->isNonSpeculative()) {
- assert(find(NonSpec, dep_inst->iqIt));
- nonSpec.erase(dep_inst->iqIt);
- } else {
- assert(find(IQ, dep_inst->iqIt));
- iq.erase(dep_inst->iqIt);
- }
-
- toBeScheduled.push_front(dep_inst);
- dep_inst->iqIt = toBeScheduled.begin();
- }
- }
- return num_outputs;
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::InstQueue::rescheduleMemInst(DynInstPtr &inst)
-{
- DPRINTF(BE, "Rescheduling memory instruction [sn:%lli]\n", inst->seqNum);
- assert(!inst->iqItValid);
- replayList.push_front(inst);
- inst->iqIt = replayList.begin();
- inst->iqItValid = true;
- ++numInsts;
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::InstQueue::replayMemInst(DynInstPtr &inst)
-{
- DPRINTF(BE, "Replaying memory instruction [sn:%lli]\n", inst->seqNum);
- assert(find(ReplayList, inst->iqIt));
- InstListIt iq_it = --replayList.end();
- InstListIt iq_end_it = replayList.end();
- while (iq_it != iq_end_it) {
- DynInstPtr rescheduled_inst = (*iq_it);
-
- DPRINTF(BE, "Memory instruction [sn:%lli] also replayed\n", inst->seqNum);
- replayList.erase(iq_it--);
- toBeScheduled.push_front(rescheduled_inst);
- rescheduled_inst->iqIt = toBeScheduled.begin();
- }
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::InstQueue::completeMemInst(DynInstPtr &inst)
-{
- panic("Not implemented.");
-}
-
-template <class Impl>
-bool
-BackEnd<Impl>::InstQueue::find(queue q, InstListIt it)
-{
- InstListIt iq_it, iq_end_it;
- switch(q) {
- case NonSpec:
- iq_it = nonSpec.begin();
- iq_end_it = nonSpec.end();
- break;
- case IQ:
- iq_it = iq.begin();
- iq_end_it = iq.end();
- break;
- case ToBeScheduled:
- iq_it = toBeScheduled.begin();
- iq_end_it = toBeScheduled.end();
- break;
- case ReadyList:
- iq_it = readyList.begin();
- iq_end_it = readyList.end();
- break;
- case ReplayList:
- iq_it = replayList.begin();
- iq_end_it = replayList.end();
- }
-
- while (iq_it != it && iq_it != iq_end_it) {
- iq_it++;
- }
- if (iq_it == it) {
- return true;
- } else {
- return false;
- }
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::InstQueue::dumpInsts()
-{
- cprintf("IQ size: %i\n", iq.size());
-
- InstListIt inst_list_it = --iq.end();
-
- int num = 0;
- int valid_num = 0;
- while (inst_list_it != iq.end())
- {
- cprintf("Instruction:%i\n",
- num);
- if (!(*inst_list_it)->isSquashed()) {
- if (!(*inst_list_it)->isIssued()) {
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- } else if ((*inst_list_it)->isMemRef() &&
- !(*inst_list_it)->memOpDone) {
- // Loads that have not been marked as executed still count
- // towards the total instructions.
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- }
- }
-
- cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
- "Issued:%i\nSquashed:%i\n",
- (*inst_list_it)->readPC(),
- (*inst_list_it)->seqNum,
- (*inst_list_it)->threadNumber,
- (*inst_list_it)->isIssued(),
- (*inst_list_it)->isSquashed());
-
- if ((*inst_list_it)->isMemRef()) {
- cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
- }
-
- cprintf("\n");
-
- inst_list_it--;
- ++num;
- }
-
- cprintf("nonSpec size: %i\n", nonSpec.size());
-
- inst_list_it = --nonSpec.end();
-
- while (inst_list_it != nonSpec.end())
- {
- cprintf("Instruction:%i\n",
- num);
- if (!(*inst_list_it)->isSquashed()) {
- if (!(*inst_list_it)->isIssued()) {
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- } else if ((*inst_list_it)->isMemRef() &&
- !(*inst_list_it)->memOpDone) {
- // Loads that have not been marked as executed still count
- // towards the total instructions.
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- }
- }
-
- cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
- "Issued:%i\nSquashed:%i\n",
- (*inst_list_it)->readPC(),
- (*inst_list_it)->seqNum,
- (*inst_list_it)->threadNumber,
- (*inst_list_it)->isIssued(),
- (*inst_list_it)->isSquashed());
-
- if ((*inst_list_it)->isMemRef()) {
- cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
- }
-
- cprintf("\n");
-
- inst_list_it--;
- ++num;
- }
-
- cprintf("toBeScheduled size: %i\n", toBeScheduled.size());
-
- inst_list_it = --toBeScheduled.end();
-
- while (inst_list_it != toBeScheduled.end())
- {
- cprintf("Instruction:%i\n",
- num);
- if (!(*inst_list_it)->isSquashed()) {
- if (!(*inst_list_it)->isIssued()) {
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- } else if ((*inst_list_it)->isMemRef() &&
- !(*inst_list_it)->memOpDone) {
- // Loads that have not been marked as executed still count
- // towards the total instructions.
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- }
- }
-
- cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
- "Issued:%i\nSquashed:%i\n",
- (*inst_list_it)->readPC(),
- (*inst_list_it)->seqNum,
- (*inst_list_it)->threadNumber,
- (*inst_list_it)->isIssued(),
- (*inst_list_it)->isSquashed());
-
- if ((*inst_list_it)->isMemRef()) {
- cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
- }
-
- cprintf("\n");
-
- inst_list_it--;
- ++num;
- }
-
- cprintf("readyList size: %i\n", readyList.size());
-
- inst_list_it = --readyList.end();
-
- while (inst_list_it != readyList.end())
- {
- cprintf("Instruction:%i\n",
- num);
- if (!(*inst_list_it)->isSquashed()) {
- if (!(*inst_list_it)->isIssued()) {
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- } else if ((*inst_list_it)->isMemRef() &&
- !(*inst_list_it)->memOpDone) {
- // Loads that have not been marked as executed still count
- // towards the total instructions.
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- }
- }
-
- cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
- "Issued:%i\nSquashed:%i\n",
- (*inst_list_it)->readPC(),
- (*inst_list_it)->seqNum,
- (*inst_list_it)->threadNumber,
- (*inst_list_it)->isIssued(),
- (*inst_list_it)->isSquashed());
-
- if ((*inst_list_it)->isMemRef()) {
- cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
- }
-
- cprintf("\n");
-
- inst_list_it--;
- ++num;
- }
-}
-
-template<class Impl>
-BackEnd<Impl>::LdWritebackEvent::LdWritebackEvent(DynInstPtr &_inst,
- BackEnd<Impl> *_be)
- : Event(&mainEventQueue), inst(_inst), be(_be)
-{
- this->setFlags(Event::AutoDelete);
-}
-
-template<class Impl>
-void
-BackEnd<Impl>::LdWritebackEvent::process()
-{
- DPRINTF(BE, "Load writeback event [sn:%lli]\n", inst->seqNum);
-// DPRINTF(Activity, "Activity: Ld Writeback event [sn:%lli]\n", inst->seqNum);
-
- //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum);
-
-// iewStage->wakeCPU();
-
- if (inst->isSquashed()) {
- inst = NULL;
- return;
- }
-
- if (!inst->isExecuted()) {
- inst->setExecuted();
-
- // Execute again to copy data to proper place.
- inst->completeAcc();
- }
-
- // Need to insert instruction into queue to commit
- be->instToCommit(inst);
-
- //wroteToTimeBuffer = true;
-// iewStage->activityThisCycle();
-
- inst = NULL;
-}
-
-template<class Impl>
-const char *
-BackEnd<Impl>::LdWritebackEvent::description()
-{
- return "Load writeback event";
-}
-
-
-template <class Impl>
-BackEnd<Impl>::DCacheCompletionEvent::DCacheCompletionEvent(BackEnd *_be)
- : Event(&mainEventQueue, CPU_Tick_Pri), be(_be)
-{
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::DCacheCompletionEvent::process()
-{
-}
-
-template <class Impl>
-const char *
-BackEnd<Impl>::DCacheCompletionEvent::description()
-{
- return "Cache completion event";
-}
-
-template <class Impl>
-BackEnd<Impl>::BackEnd(Params *params)
- : d2i(5, 5), i2e(5, 5), e2c(5, 5), numInstsToWB(5, 5),
- xcSquash(false), IQ(params),
- cacheCompletionEvent(this), width(params->backEndWidth),
- exactFullStall(true)
-{
- numROBEntries = params->numROBEntries;
- numInsts = 0;
- numDispatchEntries = 32;
- IQ.setBE(this);
- LSQ.setBE(this);
-
- // Setup IQ and LSQ with their parameters here.
- instsToDispatch = d2i.getWire(-1);
-
- instsToExecute = i2e.getWire(-1);
-
- IQ.setIssueExecQueue(&i2e);
-
- dispatchWidth = params->dispatchWidth ? params->dispatchWidth : width;
- issueWidth = params->issueWidth ? params->issueWidth : width;
- wbWidth = params->wbWidth ? params->wbWidth : width;
- commitWidth = params->commitWidth ? params->commitWidth : width;
-
- LSQ.init(params, params->LQEntries, params->SQEntries, 0);
-
- dispatchStatus = Running;
-}
-
-template <class Impl>
-std::string
-BackEnd<Impl>::name() const
-{
- return cpu->name() + ".backend";
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::regStats()
-{
- using namespace Stats;
- rob_cap_events
- .init(cpu->number_of_threads)
- .name(name() + ".ROB:cap_events")
- .desc("number of cycles where ROB cap was active")
- .flags(total)
- ;
-
- rob_cap_inst_count
- .init(cpu->number_of_threads)
- .name(name() + ".ROB:cap_inst")
- .desc("number of instructions held up by ROB cap")
- .flags(total)
- ;
-
- iq_cap_events
- .init(cpu->number_of_threads)
- .name(name() +".IQ:cap_events" )
- .desc("number of cycles where IQ cap was active")
- .flags(total)
- ;
-
- iq_cap_inst_count
- .init(cpu->number_of_threads)
- .name(name() + ".IQ:cap_inst")
- .desc("number of instructions held up by IQ cap")
- .flags(total)
- ;
-
-
- exe_inst
- .init(cpu->number_of_threads)
- .name(name() + ".ISSUE:count")
- .desc("number of insts issued")
- .flags(total)
- ;
-
- exe_swp
- .init(cpu->number_of_threads)
- .name(name() + ".ISSUE:swp")
- .desc("number of swp insts issued")
- .flags(total)
- ;
-
- exe_nop
- .init(cpu->number_of_threads)
- .name(name() + ".ISSUE:nop")
- .desc("number of nop insts issued")
- .flags(total)
- ;
-
- exe_refs
- .init(cpu->number_of_threads)
- .name(name() + ".ISSUE:refs")
- .desc("number of memory reference insts issued")
- .flags(total)
- ;
-
- exe_loads
- .init(cpu->number_of_threads)
- .name(name() + ".ISSUE:loads")
- .desc("number of load insts issued")
- .flags(total)
- ;
-
- exe_branches
- .init(cpu->number_of_threads)
- .name(name() + ".ISSUE:branches")
- .desc("Number of branches issued")
- .flags(total)
- ;
-
- issued_ops
- .init(cpu->number_of_threads)
- .name(name() + ".ISSUE:op_count")
- .desc("number of insts issued")
- .flags(total)
- ;
-
-/*
- for (int i=0; i<Num_OpClasses; ++i) {
- stringstream subname;
- subname << opClassStrings[i] << "_delay";
- issue_delay_dist.subname(i, subname.str());
- }
-*/
- //
- // Other stats
- //
- lsq_forw_loads
- .init(cpu->number_of_threads)
- .name(name() + ".LSQ:forw_loads")
- .desc("number of loads forwarded via LSQ")
- .flags(total)
- ;
-
- inv_addr_loads
- .init(cpu->number_of_threads)
- .name(name() + ".ISSUE:addr_loads")
- .desc("number of invalid-address loads")
- .flags(total)
- ;
-
- inv_addr_swpfs
- .init(cpu->number_of_threads)
- .name(name() + ".ISSUE:addr_swpfs")
- .desc("number of invalid-address SW prefetches")
- .flags(total)
- ;
-
- lsq_blocked_loads
- .init(cpu->number_of_threads)
- .name(name() + ".LSQ:blocked_loads")
- .desc("number of ready loads not issued due to memory disambiguation")
- .flags(total)
- ;
-
- lsqInversion
- .name(name() + ".ISSUE:lsq_invert")
- .desc("Number of times LSQ instruction issued early")
- ;
-
- n_issued_dist
- .init(issueWidth + 1)
- .name(name() + ".ISSUE:issued_per_cycle")
- .desc("Number of insts issued each cycle")
- .flags(total | pdf | dist)
- ;
- issue_delay_dist
- .init(Num_OpClasses,0,99,2)
- .name(name() + ".ISSUE:")
- .desc("cycles from operands ready to issue")
- .flags(pdf | cdf)
- ;
-
- queue_res_dist
- .init(Num_OpClasses, 0, 99, 2)
- .name(name() + ".IQ:residence:")
- .desc("cycles from dispatch to issue")
- .flags(total | pdf | cdf )
- ;
- for (int i = 0; i < Num_OpClasses; ++i) {
- queue_res_dist.subname(i, opClassStrings[i]);
- }
-
- writeback_count
- .init(cpu->number_of_threads)
- .name(name() + ".WB:count")
- .desc("cumulative count of insts written-back")
- .flags(total)
- ;
-
- producer_inst
- .init(cpu->number_of_threads)
- .name(name() + ".WB:producers")
- .desc("num instructions producing a value")
- .flags(total)
- ;
-
- consumer_inst
- .init(cpu->number_of_threads)
- .name(name() + ".WB:consumers")
- .desc("num instructions consuming a value")
- .flags(total)
- ;
-
- wb_penalized
- .init(cpu->number_of_threads)
- .name(name() + ".WB:penalized")
- .desc("number of instrctions required to write to 'other' IQ")
- .flags(total)
- ;
-
-
- wb_penalized_rate
- .name(name() + ".WB:penalized_rate")
- .desc ("fraction of instructions written-back that wrote to 'other' IQ")
- .flags(total)
- ;
-
- wb_penalized_rate = wb_penalized / writeback_count;
-
- wb_fanout
- .name(name() + ".WB:fanout")
- .desc("average fanout of values written-back")
- .flags(total)
- ;
-
- wb_fanout = producer_inst / consumer_inst;
-
- wb_rate
- .name(name() + ".WB:rate")
- .desc("insts written-back per cycle")
- .flags(total)
- ;
- wb_rate = writeback_count / cpu->numCycles;
-
- stat_com_inst
- .init(cpu->number_of_threads)
- .name(name() + ".COM:count")
- .desc("Number of instructions committed")
- .flags(total)
- ;
-
- stat_com_swp
- .init(cpu->number_of_threads)
- .name(name() + ".COM:swp_count")
- .desc("Number of s/w prefetches committed")
- .flags(total)
- ;
-
- stat_com_refs
- .init(cpu->number_of_threads)
- .name(name() + ".COM:refs")
- .desc("Number of memory references committed")
- .flags(total)
- ;
-
- stat_com_loads
- .init(cpu->number_of_threads)
- .name(name() + ".COM:loads")
- .desc("Number of loads committed")
- .flags(total)
- ;
-
- stat_com_membars
- .init(cpu->number_of_threads)
- .name(name() + ".COM:membars")
- .desc("Number of memory barriers committed")
- .flags(total)
- ;
-
- stat_com_branches
- .init(cpu->number_of_threads)
- .name(name() + ".COM:branches")
- .desc("Number of branches committed")
- .flags(total)
- ;
- n_committed_dist
- .init(0,commitWidth,1)
- .name(name() + ".COM:committed_per_cycle")
- .desc("Number of insts commited each cycle")
- .flags(pdf)
- ;
-
- //
- // Commit-Eligible instructions...
- //
- // -> The number of instructions eligible to commit in those
- // cycles where we reached our commit BW limit (less the number
- // actually committed)
- //
- // -> The average value is computed over ALL CYCLES... not just
- // the BW limited cycles
- //
- // -> The standard deviation is computed only over cycles where
- // we reached the BW limit
- //
- commit_eligible
- .init(cpu->number_of_threads)
- .name(name() + ".COM:bw_limited")
- .desc("number of insts not committed due to BW limits")
- .flags(total)
- ;
-
- commit_eligible_samples
- .name(name() + ".COM:bw_lim_events")
- .desc("number cycles where commit BW limit reached")
- ;
-
- ROB_fcount
- .name(name() + ".ROB:full_count")
- .desc("number of cycles where ROB was full")
- ;
-
- ROB_count
- .init(cpu->number_of_threads)
- .name(name() + ".ROB:occupancy")
- .desc(name() + ".ROB occupancy (cumulative)")
- .flags(total)
- ;
-
- ROB_full_rate
- .name(name() + ".ROB:full_rate")
- .desc("ROB full per cycle")
- ;
- ROB_full_rate = ROB_fcount / cpu->numCycles;
-
- ROB_occ_rate
- .name(name() + ".ROB:occ_rate")
- .desc("ROB occupancy rate")
- .flags(total)
- ;
- ROB_occ_rate = ROB_count / cpu->numCycles;
-
- ROB_occ_dist
- .init(cpu->number_of_threads,0,numROBEntries,2)
- .name(name() + ".ROB:occ_dist")
- .desc("ROB Occupancy per cycle")
- .flags(total | cdf)
- ;
-
- IQ.regStats();
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::setCommBuffer(TimeBuffer<CommStruct> *_comm)
-{
- comm = _comm;
- toIEW = comm->getWire(0);
- fromCommit = comm->getWire(-1);
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::tick()
-{
- DPRINTF(BE, "Ticking back end\n");
-
- ROB_count[0]+= numInsts;
-
- wbCycle = 0;
-
- if (xcSquash) {
- squashFromXC();
- }
-
- // Read in any done instruction information and update the IQ or LSQ.
- updateStructures();
-
- if (dispatchStatus != Blocked) {
- d2i.advance();
- dispatchInsts();
- } else {
- checkDispatchStatus();
- }
-
- i2e.advance();
- scheduleReadyInsts();
-
- e2c.advance();
- executeInsts();
-
- numInstsToWB.advance();
- writebackInsts();
-
- commitInsts();
-
- DPRINTF(BE, "IQ entries in use: %i, ROB entries in use: %i, LSQ loads: %i, LSQ stores: %i\n",
- IQ.numInsts, numInsts, LSQ.numLoads(), LSQ.numStores());
-
- assert(numInsts == instList.size());
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::updateStructures()
-{
- if (fromCommit->doneSeqNum) {
- IQ.commit(fromCommit->doneSeqNum);
- LSQ.commitLoads(fromCommit->doneSeqNum);
- LSQ.commitStores(fromCommit->doneSeqNum);
- }
-
- if (fromCommit->nonSpecSeqNum) {
- if (fromCommit->uncached) {
- LSQ.executeLoad(fromCommit->lqIdx);
- } else {
- IQ.scheduleNonSpec(
- fromCommit->nonSpecSeqNum);
- }
- }
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::addToIQ(DynInstPtr &inst)
-{
- // Do anything IQ specific here?
- IQ.insert(inst);
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::addToLSQ(DynInstPtr &inst)
-{
- // Do anything LSQ specific here?
- LSQ.insert(inst);
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::dispatchInsts()
-{
- DPRINTF(BE, "Trying to dispatch instructions.\n");
-
- // Pull instructions out of the front end.
- int disp_width = dispatchWidth ? dispatchWidth : width;
-
- // Could model dispatching time, but in general 1 cycle is probably
- // good enough.
-
- if (dispatchSize < numDispatchEntries) {
- for (int i = 0; i < disp_width; i++) {
- // Get instructions
- DynInstPtr inst = frontEnd->getInst();
-
- if (!inst) {
- // No more instructions to get
- break;
- }
-
- DPRINTF(BE, "Processing instruction [sn:%lli] PC:%#x\n",
- inst->seqNum, inst->readPC());
-
- for (int i = 0; i < inst->numDestRegs(); ++i)
- renameTable[inst->destRegIdx(i)] = inst;
-
- // Add to queue to be dispatched.
- dispatch.push_back(inst);
-
- d2i[0].size++;
- ++dispatchSize;
- }
- }
-
- assert(dispatch.size() < 64);
-
- for (int i = 0; i < instsToDispatch->size; ++i) {
- assert(!dispatch.empty());
- // Get instruction from front of time buffer
- DynInstPtr inst = dispatch.front();
- dispatch.pop_front();
- --dispatchSize;
-
- if (inst->isSquashed())
- continue;
-
- ++numInsts;
- instList.push_back(inst);
-
- DPRINTF(BE, "Dispatching instruction [sn:%lli] PC:%#x\n",
- inst->seqNum, inst->readPC());
-
- addToIQ(inst);
-
- if (inst->isMemRef()) {
- addToLSQ(inst);
- }
-
- if (inst->isNonSpeculative()) {
- inst->setCanCommit();
- }
-
- // Check if IQ or LSQ is full. If so we'll need to break and stop
- // removing instructions. Also update the number of insts to remove
- // from the queue.
- if (exactFullStall) {
- bool stall = false;
- if (IQ.isFull()) {
- DPRINTF(BE, "IQ is full!\n");
- stall = true;
- } else if (LSQ.isFull()) {
- DPRINTF(BE, "LSQ is full!\n");
- stall = true;
- } else if (isFull()) {
- DPRINTF(BE, "ROB is full!\n");
- stall = true;
- ROB_fcount++;
- }
- if (stall) {
- instsToDispatch->size-= i+1;
- dispatchStall();
- return;
- }
- }
- }
-
- // Check if IQ or LSQ is full. If so we'll need to break and stop
- // removing instructions. Also update the number of insts to remove
- // from the queue. Check here if we don't care about exact stall
- // conditions.
-
- bool stall = false;
- if (IQ.isFull()) {
- DPRINTF(BE, "IQ is full!\n");
- stall = true;
- } else if (LSQ.isFull()) {
- DPRINTF(BE, "LSQ is full!\n");
- stall = true;
- } else if (isFull()) {
- DPRINTF(BE, "ROB is full!\n");
- stall = true;
- ROB_fcount++;
- }
- if (stall) {
- d2i.advance();
- dispatchStall();
- return;
- }
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::dispatchStall()
-{
- dispatchStatus = Blocked;
- if (!cpu->decoupledFrontEnd) {
- // Tell front end to stall here through a timebuffer, or just tell
- // it directly.
- }
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::checkDispatchStatus()
-{
- DPRINTF(BE, "Checking dispatch status\n");
- assert(dispatchStatus == Blocked);
- if (!IQ.isFull() && !LSQ.isFull() && !isFull()) {
- DPRINTF(BE, "Dispatch no longer blocked\n");
- dispatchStatus = Running;
- dispatchInsts();
- }
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::scheduleReadyInsts()
-{
- // Tell IQ to put any ready instructions into the instruction list.
- // Probably want to have a list of DynInstPtrs returned here. Then I
- // can choose to either put them into a time buffer to simulate
- // IQ scheduling time, or hand them directly off to the next stage.
- // Do you ever want to directly hand it off to the next stage?
- DPRINTF(BE, "Trying to schedule ready instructions\n");
- IQ.scheduleReadyInsts();
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::executeInsts()
-{
- int insts_to_execute = instsToExecute->size;
-
- issued_ops[0]+= insts_to_execute;
- n_issued_dist[insts_to_execute]++;
-
- DPRINTF(BE, "Trying to execute %i instructions\n", insts_to_execute);
-
- fetchRedirect[0] = false;
-
- while (insts_to_execute > 0) {
- // Get ready instruction from the IQ (or queue coming out of IQ)
- // Execute the ready instruction.
- // Wakeup any dependents if it's done.
- DynInstPtr inst = IQ.getReadyInst();
-
- DPRINTF(BE, "Executing inst [sn:%lli] PC: %#x\n",
- inst->seqNum, inst->readPC());
-
- ++funcExeInst;
-
- // Check if the instruction is squashed; if so then skip it
- // and don't count it towards the FU usage.
- if (inst->isSquashed()) {
- DPRINTF(BE, "Execute: Instruction was squashed.\n");
-
- // Not sure how to handle this plus the method of sending # of
- // instructions to use. Probably will just have to count it
- // towards the bandwidth usage, but not the FU usage.
- --insts_to_execute;
-
- // Consider this instruction executed so that commit can go
- // ahead and retire the instruction.
- inst->setExecuted();
-
- // Not sure if I should set this here or just let commit try to
- // commit any squashed instructions. I like the latter a bit more.
- inst->setCanCommit();
-
-// ++iewExecSquashedInsts;
-
- continue;
- }
-
- Fault fault = NoFault;
-
- // Execute instruction.
- // Note that if the instruction faults, it will be handled
- // at the commit stage.
- if (inst->isMemRef() &&
- (!inst->isDataPrefetch() && !inst->isInstPrefetch())) {
- DPRINTF(BE, "Execute: Initiating access for memory "
- "reference.\n");
-
- // Tell the LDSTQ to execute this instruction (if it is a load).
- if (inst->isLoad()) {
- // Loads will mark themselves as executed, and their writeback
- // event adds the instruction to the queue to commit
- fault = LSQ.executeLoad(inst);
-
-// ++iewExecLoadInsts;
- } else if (inst->isStore()) {
- LSQ.executeStore(inst);
-
-// ++iewExecStoreInsts;
-
- if (!(inst->req->flags & LOCKED)) {
- inst->setExecuted();
-
- instToCommit(inst);
- }
- // Store conditionals will mark themselves as executed, and
- // their writeback event will add the instruction to the queue
- // to commit.
- } else {
- panic("Unexpected memory type!\n");
- }
-
- } else {
- inst->execute();
-
-// ++iewExecutedInsts;
-
- inst->setExecuted();
-
- instToCommit(inst);
- }
-
- updateExeInstStats(inst);
-
- // Probably should have some sort of function for this.
- // More general question of how to handle squashes? Have some sort of
- // squash unit that controls it? Probably...
- // Check if branch was correct. This check happens after the
- // instruction is added to the queue because even if the branch
- // is mispredicted, the branch instruction itself is still valid.
- // Only handle this if there hasn't already been something that
- // redirects fetch in this group of instructions.
-
- // This probably needs to prioritize the redirects if a different
- // scheduler is used. Currently the scheduler schedules the oldest
- // instruction first, so the branch resolution order will be correct.
- unsigned tid = inst->threadNumber;
-
- if (!fetchRedirect[tid]) {
-
- if (inst->mispredicted()) {
- fetchRedirect[tid] = true;
-
- DPRINTF(BE, "Execute: Branch mispredict detected.\n");
- DPRINTF(BE, "Execute: Redirecting fetch to PC: %#x.\n",
- inst->nextPC);
-
- // If incorrect, then signal the ROB that it must be squashed.
- squashDueToBranch(inst);
-
- if (inst->predTaken()) {
-// predictedTakenIncorrect++;
- } else {
-// predictedNotTakenIncorrect++;
- }
- } else if (LSQ.violation()) {
- fetchRedirect[tid] = true;
-
- // Get the DynInst that caused the violation. Note that this
- // clears the violation signal.
- DynInstPtr violator;
- violator = LSQ.getMemDepViolator();
-
- DPRINTF(BE, "LDSTQ detected a violation. Violator PC: "
- "%#x, inst PC: %#x. Addr is: %#x.\n",
- violator->readPC(), inst->readPC(), inst->physEffAddr);
-
- // Tell the instruction queue that a violation has occured.
-// IQ.violation(inst, violator);
-
- // Squash.
-// squashDueToMemOrder(inst,tid);
- squashDueToBranch(inst);
-
-// ++memOrderViolationEvents;
- } else if (LSQ.loadBlocked()) {
- fetchRedirect[tid] = true;
-
- DPRINTF(BE, "Load operation couldn't execute because the "
- "memory system is blocked. PC: %#x [sn:%lli]\n",
- inst->readPC(), inst->seqNum);
-
- squashDueToMemBlocked(inst);
- }
- }
-
-// instList.pop_front();
-
- --insts_to_execute;
-
- // keep an instruction count
- thread->numInst++;
- thread->numInsts++;
- }
-
- assert(insts_to_execute >= 0);
-}
-
-template<class Impl>
-void
-BackEnd<Impl>::instToCommit(DynInstPtr &inst)
-{
- int wb_width = wbWidth;
- // First check the time slot that this instruction will write
- // to. If there are free write ports at the time, then go ahead
- // and write the instruction to that time. If there are not,
- // keep looking back to see where's the first time there's a
- // free slot. What happens if you run out of free spaces?
- // For now naively assume that all instructions take one cycle.
- // Otherwise would have to look into the time buffer based on the
- // latency of the instruction.
-
- DPRINTF(BE, "Sending instructions to commit [sn:%lli] PC %#x.\n",
- inst->seqNum, inst->readPC());
-
- while (numInstsToWB[wbCycle].size >= wb_width) {
- ++wbCycle;
-
- assert(wbCycle < 5);
- }
-
- // Add finished instruction to queue to commit.
- writeback.push_back(inst);
- numInstsToWB[wbCycle].size++;
-
- if (wbCycle)
- wb_penalized[0]++;
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::writebackInsts()
-{
- int wb_width = wbWidth;
- // Using this method I'm not quite sure how to prevent an
- // instruction from waking its own dependents multiple times,
- // without the guarantee that commit always has enough bandwidth
- // to accept all instructions being written back. This guarantee
- // might not be too unrealistic.
- InstListIt wb_inst_it = writeback.begin();
- InstListIt wb_end_it = writeback.end();
- int inst_num = 0;
- int consumer_insts = 0;
-
- for (; inst_num < wb_width &&
- wb_inst_it != wb_end_it; inst_num++) {
- DynInstPtr inst = (*wb_inst_it);
-
- // Some instructions will be sent to commit without having
- // executed because they need commit to handle them.
- // E.g. Uncached loads have not actually executed when they
- // are first sent to commit. Instead commit must tell the LSQ
- // when it's ready to execute the uncached load.
- if (!inst->isSquashed()) {
- DPRINTF(BE, "Writing back instruction [sn:%lli] PC %#x.\n",
- inst->seqNum, inst->readPC());
-
- inst->setCanCommit();
- inst->setResultReady();
-
- if (inst->isExecuted()) {
- int dependents = IQ.wakeDependents(inst);
- if (dependents) {
- producer_inst[0]++;
- consumer_insts+= dependents;
- }
- }
- }
-
- writeback.erase(wb_inst_it++);
- }
- LSQ.writebackStores();
- consumer_inst[0]+= consumer_insts;
- writeback_count[0]+= inst_num;
-}
-
-template <class Impl>
-bool
-BackEnd<Impl>::commitInst(int inst_num)
-{
- // Read instruction from the head of the ROB
- DynInstPtr inst = instList.front();
-
- // Make sure instruction is valid
- assert(inst);
-
- if (!inst->readyToCommit())
- return false;
-
- DPRINTF(BE, "Trying to commit instruction [sn:%lli] PC:%#x\n",
- inst->seqNum, inst->readPC());
-
- // If the instruction is not executed yet, then it is a non-speculative
- // or store inst. Signal backwards that it should be executed.
- if (!inst->isExecuted()) {
- // Keep this number correct. We have not yet actually executed
- // and committed this instruction.
-// thread->funcExeInst--;
-
- if (inst->isNonSpeculative()) {
-#if !FULL_SYSTEM
- // Hack to make sure syscalls aren't executed until all stores
- // write back their data. This direct communication shouldn't
- // be used for anything other than this.
- if (inst_num > 0 || LSQ.hasStoresToWB()) {
- DPRINTF(BE, "Waiting for all stores to writeback.\n");
- return false;
- }
-#endif
-
- DPRINTF(BE, "Encountered a store or non-speculative "
- "instruction at the head of the ROB, PC %#x.\n",
- inst->readPC());
-
- // Send back the non-speculative instruction's sequence number.
- toIEW->nonSpecSeqNum = inst->seqNum;
-
- // Change the instruction so it won't try to commit again until
- // it is executed.
- inst->clearCanCommit();
-
-// ++commitNonSpecStalls;
-
- return false;
- } else if (inst->isLoad()) {
- DPRINTF(BE, "[sn:%lli]: Uncached load, PC %#x.\n",
- inst->seqNum, inst->readPC());
-
- // Send back the non-speculative instruction's sequence
- // number. Maybe just tell the lsq to re-execute the load.
- toIEW->nonSpecSeqNum = inst->seqNum;
- toIEW->uncached = true;
- toIEW->lqIdx = inst->lqIdx;
-
- inst->clearCanCommit();
-
- return false;
- } else {
- panic("Trying to commit un-executed instruction "
- "of unknown type!\n");
- }
- }
-
- // Now check if it's one of the special trap or barrier or
- // serializing instructions.
- if (inst->isThreadSync())
- {
- // Not handled for now.
- panic("Barrier instructions are not handled yet.\n");
- }
-
- // Check if the instruction caused a fault. If so, trap.
- Fault inst_fault = inst->getFault();
-
- if (inst_fault != NoFault) {
- if (!inst->isNop()) {
-#if FULL_SYSTEM
- DPRINTF(BE, "Inst [sn:%lli] PC %#x has a fault\n",
- inst->seqNum, inst->readPC());
-
-// assert(!thread->inSyscall);
-
-// thread->inSyscall = true;
-
- // Consider holding onto the trap and waiting until the trap event
- // happens for this to be executed.
- inst_fault->invoke(thread->getXCProxy());
-
- // Exit state update mode to avoid accidental updating.
-// thread->inSyscall = false;
-
-// commitStatus = TrapPending;
-
- // Generate trap squash event.
-// generateTrapEvent();
-
- return false;
-#else // !FULL_SYSTEM
- panic("fault (%d) detected @ PC %08p", inst_fault,
- inst->PC);
-#endif // FULL_SYSTEM
- }
- }
-
- if (inst->isControl()) {
-// ++commitCommittedBranches;
- }
-
- int freed_regs = 0;
-
- for (int i = 0; i < inst->numDestRegs(); ++i) {
- DPRINTF(BE, "Commit rename map setting register %i to [sn:%lli]\n",
- (int)inst->destRegIdx(i), inst->seqNum);
- thread->renameTable[inst->destRegIdx(i)] = inst;
- ++freed_regs;
- }
-
- if (inst->traceData) {
- inst->traceData->finalize();
- inst->traceData = NULL;
- }
-
- inst->clearDependents();
-
- frontEnd->addFreeRegs(freed_regs);
-
- instList.pop_front();
-
- --numInsts;
- cpu->numInst++;
- thread->numInsts++;
- ++thread->funcExeInst;
- thread->PC = inst->readNextPC();
- updateComInstStats(inst);
-
- // Write the done sequence number here.
- toIEW->doneSeqNum = inst->seqNum;
-
-#if FULL_SYSTEM
- int count = 0;
- Addr oldpc;
- do {
- if (count == 0)
- assert(!thread->inSyscall && !thread->trapPending);
- oldpc = thread->readPC();
- cpu->system->pcEventQueue.service(
- thread->getXCProxy());
- count++;
- } while (oldpc != thread->readPC());
- if (count > 1) {
- DPRINTF(BE, "PC skip function event, stopping commit\n");
-// completed_last_inst = false;
-// squashPending = true;
- return false;
- }
-#endif
- return true;
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::commitInsts()
-{
- int commit_width = commitWidth ? commitWidth : width;
-
- // Not sure this should be a loop or not.
- int inst_num = 0;
- while (!instList.empty() && inst_num < commit_width) {
- if (instList.front()->isSquashed()) {
- panic("No squashed insts should still be on the list!");
- instList.front()->clearDependents();
- instList.pop_front();
- continue;
- }
-
- if (!commitInst(inst_num++)) {
- break;
- }
- }
- n_committed_dist.sample(inst_num);
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::squash(const InstSeqNum &sn)
-{
- IQ.squash(sn);
- LSQ.squash(sn);
-
- int freed_regs = 0;
- InstListIt dispatch_end = dispatch.end();
- InstListIt insts_it = dispatch.end();
- insts_it--;
-
- while (insts_it != dispatch_end && (*insts_it)->seqNum > sn)
- {
- if ((*insts_it)->isSquashed()) {
- --insts_it;
- continue;
- }
- DPRINTF(BE, "Squashing instruction on dispatch list PC %#x, [sn:%lli].\n",
- (*insts_it)->readPC(),
- (*insts_it)->seqNum);
-
- // Mark the instruction as squashed, and ready to commit so that
- // it can drain out of the pipeline.
- (*insts_it)->setSquashed();
-
- (*insts_it)->setCanCommit();
-
- // Be careful with IPRs and such here
- for (int i = 0; i < (*insts_it)->numDestRegs(); ++i) {
- DynInstPtr prev_dest = (*insts_it)->getPrevDestInst(i);
- DPRINTF(BE, "Commit rename map setting register %i to [sn:%lli]\n",
- (int)(*insts_it)->destRegIdx(i), prev_dest);
- renameTable[(*insts_it)->destRegIdx(i)] = prev_dest;
- ++freed_regs;
- }
-
- (*insts_it)->clearDependents();
-
- --insts_it;
- }
-
- insts_it = instList.end();
- insts_it--;
-
- while (!instList.empty() && (*insts_it)->seqNum > sn)
- {
- if ((*insts_it)->isSquashed()) {
- --insts_it;
- continue;
- }
- DPRINTF(BE, "Squashing instruction on inst list PC %#x, [sn:%lli].\n",
- (*insts_it)->readPC(),
- (*insts_it)->seqNum);
-
- // Mark the instruction as squashed, and ready to commit so that
- // it can drain out of the pipeline.
- (*insts_it)->setSquashed();
-
- (*insts_it)->setCanCommit();
-
- for (int i = 0; i < (*insts_it)->numDestRegs(); ++i) {
- DynInstPtr prev_dest = (*insts_it)->getPrevDestInst(i);
- DPRINTF(BE, "Commit rename map setting register %i to [sn:%lli]\n",
- (int)(*insts_it)->destRegIdx(i), prev_dest);
- renameTable[(*insts_it)->destRegIdx(i)] = prev_dest;
- ++freed_regs;
- }
-
- (*insts_it)->clearDependents();
-
- instList.erase(insts_it--);
- --numInsts;
- }
-
- frontEnd->addFreeRegs(freed_regs);
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::squashFromXC()
-{
- xcSquash = true;
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::squashDueToBranch(DynInstPtr &inst)
-{
- // Update the branch predictor state I guess
- squash(inst->seqNum);
- frontEnd->squash(inst->seqNum, inst->readNextPC(),
- true, inst->mispredicted());
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::squashDueToMemBlocked(DynInstPtr &inst)
-{
- DPRINTF(IEW, "Memory blocked, squashing load and younger insts, "
- "PC: %#x [sn:%i].\n", inst->readPC(), inst->seqNum);
-
- squash(inst->seqNum - 1);
- frontEnd->squash(inst->seqNum - 1, inst->readPC());
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::fetchFault(Fault &fault)
-{
- faultFromFetch = fault;
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::updateExeInstStats(DynInstPtr &inst)
-{
- int thread_number = inst->threadNumber;
-
- //
- // Pick off the software prefetches
- //
-#ifdef TARGET_ALPHA
- if (inst->isDataPrefetch())
- exe_swp[thread_number]++;
- else
- exe_inst[thread_number]++;
-#else
- exe_inst[thread_number]++;
-#endif
-
- //
- // Control operations
- //
- if (inst->isControl())
- exe_branches[thread_number]++;
-
- //
- // Memory operations
- //
- if (inst->isMemRef()) {
- exe_refs[thread_number]++;
-
- if (inst->isLoad())
- exe_loads[thread_number]++;
- }
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::updateComInstStats(DynInstPtr &inst)
-{
- unsigned thread = inst->threadNumber;
-
- //
- // Pick off the software prefetches
- //
-#ifdef TARGET_ALPHA
- if (inst->isDataPrefetch()) {
- stat_com_swp[thread]++;
- } else {
- stat_com_inst[thread]++;
- }
-#else
- stat_com_inst[thread]++;
-#endif
-
- //
- // Control Instructions
- //
- if (inst->isControl())
- stat_com_branches[thread]++;
-
- //
- // Memory references
- //
- if (inst->isMemRef()) {
- stat_com_refs[thread]++;
-
- if (inst->isLoad()) {
- stat_com_loads[thread]++;
- }
- }
-
- if (inst->isMemBarrier()) {
- stat_com_membars[thread]++;
- }
-}
-
-template <class Impl>
-void
-BackEnd<Impl>::dumpInsts()
-{
- int num = 0;
- int valid_num = 0;
-
- InstListIt inst_list_it = instList.begin();
-
- cprintf("Inst list size: %i\n", instList.size());
-
- while (inst_list_it != instList.end())
- {
- cprintf("Instruction:%i\n",
- num);
- if (!(*inst_list_it)->isSquashed()) {
- if (!(*inst_list_it)->isIssued()) {
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- } else if ((*inst_list_it)->isMemRef() &&
- !(*inst_list_it)->memOpDone) {
- // Loads that have not been marked as executed still count
- // towards the total instructions.
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- }
- }
-
- cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
- "Issued:%i\nSquashed:%i\n",
- (*inst_list_it)->readPC(),
- (*inst_list_it)->seqNum,
- (*inst_list_it)->threadNumber,
- (*inst_list_it)->isIssued(),
- (*inst_list_it)->isSquashed());
-
- if ((*inst_list_it)->isMemRef()) {
- cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
- }
-
- cprintf("\n");
-
- inst_list_it++;
- ++num;
- }
-
- cprintf("Dispatch list size: %i\n", dispatch.size());
-
- inst_list_it = dispatch.begin();
-
- while (inst_list_it != dispatch.end())
- {
- cprintf("Instruction:%i\n",
- num);
- if (!(*inst_list_it)->isSquashed()) {
- if (!(*inst_list_it)->isIssued()) {
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- } else if ((*inst_list_it)->isMemRef() &&
- !(*inst_list_it)->memOpDone) {
- // Loads that have not been marked as executed still count
- // towards the total instructions.
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- }
- }
-
- cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
- "Issued:%i\nSquashed:%i\n",
- (*inst_list_it)->readPC(),
- (*inst_list_it)->seqNum,
- (*inst_list_it)->threadNumber,
- (*inst_list_it)->isIssued(),
- (*inst_list_it)->isSquashed());
-
- if ((*inst_list_it)->isMemRef()) {
- cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
- }
-
- cprintf("\n");
-
- inst_list_it++;
- ++num;
- }
-
- cprintf("Writeback list size: %i\n", writeback.size());
-
- inst_list_it = writeback.begin();
-
- while (inst_list_it != writeback.end())
- {
- cprintf("Instruction:%i\n",
- num);
- if (!(*inst_list_it)->isSquashed()) {
- if (!(*inst_list_it)->isIssued()) {
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- } else if ((*inst_list_it)->isMemRef() &&
- !(*inst_list_it)->memOpDone) {
- // Loads that have not been marked as executed still count
- // towards the total instructions.
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- }
- }
-
- cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
- "Issued:%i\nSquashed:%i\n",
- (*inst_list_it)->readPC(),
- (*inst_list_it)->seqNum,
- (*inst_list_it)->threadNumber,
- (*inst_list_it)->isIssued(),
- (*inst_list_it)->isSquashed());
-
- if ((*inst_list_it)->isMemRef()) {
- cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
- }
-
- cprintf("\n");
-
- inst_list_it++;
- ++num;
- }
-}
diff --git a/cpu/ozone/cpu.cc b/cpu/ozone/cpu.cc
deleted file mode 100644
index d2ea0164c..000000000
--- a/cpu/ozone/cpu.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/ozone/cpu_impl.hh"
-#include "cpu/ozone/ozone_impl.hh"
-#include "cpu/ozone/simple_impl.hh"
-
-template class OzoneCPU<SimpleImpl>;
-template class OzoneCPU<OzoneImpl>;
diff --git a/cpu/ozone/cpu.hh b/cpu/ozone/cpu.hh
deleted file mode 100644
index 5af2b02b2..000000000
--- a/cpu/ozone/cpu.hh
+++ /dev/null
@@ -1,629 +0,0 @@
-/*
- * Copyright (c) 2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_OZONE_CPU_HH__
-#define __CPU_OZONE_CPU_HH__
-
-#include <set>
-
-#include "base/statistics.hh"
-#include "base/timebuf.hh"
-#include "config/full_system.hh"
-#include "cpu/base.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/inst_seq.hh"
-#include "cpu/ozone/rename_table.hh"
-#include "cpu/ozone/thread_state.hh"
-#include "cpu/pc_event.hh"
-#include "cpu/static_inst.hh"
-#include "mem/mem_interface.hh"
-#include "sim/eventq.hh"
-
-// forward declarations
-#if FULL_SYSTEM
-#include "arch/alpha/tlb.hh"
-
-class AlphaITB;
-class AlphaDTB;
-class PhysicalMemory;
-class MemoryController;
-
-class Sampler;
-class RemoteGDB;
-class GDBListener;
-
-namespace Kernel {
- class Statistics;
-};
-
-#else
-
-class Process;
-
-#endif // FULL_SYSTEM
-
-class Checkpoint;
-class EndQuiesceEvent;
-class MemInterface;
-
-namespace Trace {
- class InstRecord;
-}
-
-template <class>
-class Checker;
-
-/**
- * Declaration of Out-of-Order CPU class. Basically it is a SimpleCPU with
- * simple out-of-order capabilities added to it. It is still a 1 CPI machine
- * (?), but is capable of handling cache misses. Basically it models having
- * a ROB/IQ by only allowing a certain amount of instructions to execute while
- * the cache miss is outstanding.
- */
-
-template <class Impl>
-class OzoneCPU : public BaseCPU
-{
- private:
- typedef typename Impl::FrontEnd FrontEnd;
- typedef typename Impl::BackEnd BackEnd;
- typedef typename Impl::DynInst DynInst;
- typedef typename Impl::DynInstPtr DynInstPtr;
-
- typedef TheISA::MiscReg MiscReg;
-
- public:
- class OzoneXC : public ExecContext {
- public:
- OzoneCPU<Impl> *cpu;
-
- OzoneThreadState<Impl> *thread;
-
- BaseCPU *getCpuPtr();
-
- void setCpuId(int id);
-
- int readCpuId() { return thread->cpuId; }
-
- FunctionalMemory *getMemPtr() { return thread->mem; }
-
-#if FULL_SYSTEM
- System *getSystemPtr() { return cpu->system; }
-
- PhysicalMemory *getPhysMemPtr() { return cpu->physmem; }
-
- AlphaITB *getITBPtr() { return cpu->itb; }
-
- AlphaDTB * getDTBPtr() { return cpu->dtb; }
-
- Kernel::Statistics *getKernelStats() { return thread->kernelStats; }
-#else
- Process *getProcessPtr() { return thread->process; }
-#endif
-
- Status status() const { return thread->_status; }
-
- void setStatus(Status new_status);
-
- /// Set the status to Active. Optional delay indicates number of
- /// cycles to wait before beginning execution.
- void activate(int delay = 1);
-
- /// Set the status to Suspended.
- void suspend();
-
- /// Set the status to Unallocated.
- void deallocate();
-
- /// Set the status to Halted.
- void halt();
-
-#if FULL_SYSTEM
- void dumpFuncProfile();
-#endif
-
- void takeOverFrom(ExecContext *old_context);
-
- void regStats(const std::string &name);
-
- void serialize(std::ostream &os);
- void unserialize(Checkpoint *cp, const std::string &section);
-
-#if FULL_SYSTEM
- EndQuiesceEvent *getQuiesceEvent();
-
- Tick readLastActivate();
- Tick readLastSuspend();
-
- void profileClear();
- void profileSample();
-#endif
-
- int getThreadNum();
-
- // Also somewhat obnoxious. Really only used for the TLB fault.
- TheISA::MachInst getInst();
-
- void copyArchRegs(ExecContext *xc);
-
- void clearArchRegs();
-
- uint64_t readIntReg(int reg_idx);
-
- float readFloatRegSingle(int reg_idx);
-
- double readFloatRegDouble(int reg_idx);
-
- uint64_t readFloatRegInt(int reg_idx);
-
- void setIntReg(int reg_idx, uint64_t val);
-
- void setFloatRegSingle(int reg_idx, float val);
-
- void setFloatRegDouble(int reg_idx, double val);
-
- void setFloatRegInt(int reg_idx, uint64_t val);
-
- uint64_t readPC() { return thread->PC; }
- void setPC(Addr val);
-
- uint64_t readNextPC() { return thread->nextPC; }
- void setNextPC(Addr val);
-
- public:
- // ISA stuff:
- MiscReg readMiscReg(int misc_reg);
-
- MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault);
-
- Fault setMiscReg(int misc_reg, const MiscReg &val);
-
- Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val);
-
- unsigned readStCondFailures()
- { return thread->storeCondFailures; }
-
- void setStCondFailures(unsigned sc_failures)
- { thread->storeCondFailures = sc_failures; }
-
-#if FULL_SYSTEM
- bool inPalMode() { return cpu->inPalMode(); }
-#endif
-
- bool misspeculating() { return false; }
-
-#if !FULL_SYSTEM
- TheISA::IntReg getSyscallArg(int i)
- { return thread->renameTable[TheISA::ArgumentReg0 + i]->readIntResult(); }
-
- // used to shift args for indirect syscall
- void setSyscallArg(int i, TheISA::IntReg val)
- { thread->renameTable[TheISA::ArgumentReg0 + i]->setIntResult(i); }
-
- void setSyscallReturn(SyscallReturn return_value)
- { cpu->setSyscallReturn(return_value, thread->tid); }
-
- Counter readFuncExeInst() { return thread->funcExeInst; }
-
- void setFuncExeInst(Counter new_val)
- { thread->funcExeInst = new_val; }
-#endif
- };
-
- // execution context proxy
- OzoneXC ozoneXC;
- ExecContext *xcProxy;
- ExecContext *checkerXC;
-
- typedef OzoneThreadState<Impl> ImplState;
-
- private:
- OzoneThreadState<Impl> thread;
-
- public:
- // main simulation loop (one cycle)
- void tick();
-
- std::set<InstSeqNum> snList;
- std::set<Addr> lockAddrList;
- private:
- struct TickEvent : public Event
- {
- OzoneCPU *cpu;
- int width;
-
- TickEvent(OzoneCPU *c, int w);
- void process();
- const char *description();
- };
-
- TickEvent tickEvent;
-
- /// Schedule tick event, regardless of its current state.
- void scheduleTickEvent(int delay)
- {
- if (tickEvent.squashed())
- tickEvent.reschedule(curTick + cycles(delay));
- else if (!tickEvent.scheduled())
- tickEvent.schedule(curTick + cycles(delay));
- }
-
- /// Unschedule tick event, regardless of its current state.
- void unscheduleTickEvent()
- {
- if (tickEvent.scheduled())
- tickEvent.squash();
- }
-
- private:
- Trace::InstRecord *traceData;
-
- template<typename T>
- void trace_data(T data);
-
- public:
- enum Status {
- Running,
- Idle,
- SwitchedOut
- };
-
- Status _status;
-
- public:
- bool checkInterrupts;
-
- void post_interrupt(int int_num, int index);
-
- void zero_fill_64(Addr addr) {
- static int warned = 0;
- if (!warned) {
- warn ("WH64 is not implemented");
- warned = 1;
- }
- };
-
- typedef typename Impl::Params Params;
-
- OzoneCPU(Params *params);
-
- virtual ~OzoneCPU();
-
- void init();
-
- public:
- BaseCPU *getCpuPtr() { return this; }
-
- void setCpuId(int id) { cpuId = id; }
-
- int readCpuId() { return cpuId; }
-
- int cpuId;
-
- void switchOut(Sampler *sampler);
- void signalSwitched();
- void takeOverFrom(BaseCPU *oldCPU);
-
- Sampler *sampler;
-
- int switchCount;
-
-#if FULL_SYSTEM
- Addr dbg_vtophys(Addr addr);
-
- bool interval_stats;
-
- AlphaITB *itb;
- AlphaDTB *dtb;
- System *system;
-
- // the following two fields are redundant, since we can always
- // look them up through the system pointer, but we'll leave them
- // here for now for convenience
- MemoryController *memctrl;
- PhysicalMemory *physmem;
-#endif
-
- // L1 instruction cache
- MemInterface *icacheInterface;
-
- // L1 data cache
- MemInterface *dcacheInterface;
-
- /** Pointer to memory. */
- FunctionalMemory *mem;
-
- FrontEnd *frontEnd;
-
- BackEnd *backEnd;
- private:
- Status status() const { return _status; }
- void setStatus(Status new_status) { _status = new_status; }
-
- virtual void activateContext(int thread_num, int delay);
- virtual void suspendContext(int thread_num);
- virtual void deallocateContext(int thread_num);
- virtual void haltContext(int thread_num);
-
- // statistics
- virtual void regStats();
- virtual void resetStats();
-
- // number of simulated instructions
- public:
- Counter numInst;
- Counter startNumInst;
-
- virtual Counter totalInstructions() const
- {
- return numInst - startNumInst;
- }
-
- private:
- // number of simulated loads
- Counter numLoad;
- Counter startNumLoad;
-
- // number of idle cycles
- Stats::Average<> notIdleFraction;
- Stats::Formula idleFraction;
- public:
-
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-
-
-#if FULL_SYSTEM
- bool validInstAddr(Addr addr) { return true; }
- bool validDataAddr(Addr addr) { return true; }
-
- Fault translateInstReq(MemReqPtr &req)
- {
- return itb->translate(req);
- }
-
- Fault translateDataReadReq(MemReqPtr &req)
- {
- return dtb->translate(req, false);
- }
-
- Fault translateDataWriteReq(MemReqPtr &req)
- {
- return dtb->translate(req, true);
- }
-
-#else
- bool validInstAddr(Addr addr)
- { return true; }
-
- bool validDataAddr(Addr addr)
- { return true; }
-
- int getInstAsid() { return thread.asid; }
- int getDataAsid() { return thread.asid; }
-
- Fault dummyTranslation(MemReqPtr &req)
- {
-#if 0
- assert((req->vaddr >> 48 & 0xffff) == 0);
-#endif
-
- // put the asid in the upper 16 bits of the paddr
- req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
- req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
- return NoFault;
- }
-
- /** Translates instruction requestion in syscall emulation mode. */
- Fault translateInstReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
-
- /** Translates data read request in syscall emulation mode. */
- Fault translateDataReadReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
-
- /** Translates data write request in syscall emulation mode. */
- Fault translateDataWriteReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
-#endif
-
- /** Old CPU read from memory function. No longer used. */
- template <class T>
- Fault read(MemReqPtr &req, T &data)
- {
-#if 0
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
- if (req->flags & LOCKED) {
- req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
- req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
- }
-#endif
-#endif
- Fault error;
- if (req->flags & LOCKED) {
- lockAddrList.insert(req->paddr);
- lockFlag = true;
- }
-
- error = this->mem->read(req, data);
- data = gtoh(data);
- return error;
- }
-
-
- /** CPU read function, forwards read to LSQ. */
- template <class T>
- Fault read(MemReqPtr &req, T &data, int load_idx)
- {
- return backEnd->read(req, data, load_idx);
- }
-
- /** Old CPU write to memory function. No longer used. */
- template <class T>
- Fault write(MemReqPtr &req, T &data)
- {
-#if 0
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
- ExecContext *xc;
-
- // If this is a store conditional, act appropriately
- if (req->flags & LOCKED) {
- xc = req->xc;
-
- if (req->flags & UNCACHEABLE) {
- // Don't update result register (see stq_c in isa_desc)
- req->result = 2;
- xc->setStCondFailures(0);//Needed? [RGD]
- } else {
- bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag);
- Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag);
- req->result = lock_flag;
- if (!lock_flag ||
- ((lock_addr & ~0xf) != (req->paddr & ~0xf))) {
- xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
- xc->setStCondFailures(xc->readStCondFailures() + 1);
- if (((xc->readStCondFailures()) % 100000) == 0) {
- std::cerr << "Warning: "
- << xc->readStCondFailures()
- << " consecutive store conditional failures "
- << "on cpu " << req->xc->readCpuId()
- << std::endl;
- }
- return NoFault;
- }
- else xc->setStCondFailures(0);
- }
- }
-
- // Need to clear any locked flags on other proccessors for
- // this address. Only do this for succsful Store Conditionals
- // and all other stores (WH64?). Unsuccessful Store
- // Conditionals would have returned above, and wouldn't fall
- // through.
- for (int i = 0; i < this->system->execContexts.size(); i++){
- xc = this->system->execContexts[i];
- if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
- (req->paddr & ~0xf)) {
- xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
- }
- }
-
-#endif
-#endif
-
- if (req->flags & LOCKED) {
- if (req->flags & UNCACHEABLE) {
- req->result = 2;
- } else {
- if (this->lockFlag) {
- if (lockAddrList.find(req->paddr) !=
- lockAddrList.end()) {
- req->result = 1;
- } else {
- req->result = 0;
- return NoFault;
- }
- } else {
- req->result = 0;
- return NoFault;
- }
- }
- }
-
- return this->mem->write(req, (T)htog(data));
- }
-
- /** CPU write function, forwards write to LSQ. */
- template <class T>
- Fault write(MemReqPtr &req, T &data, int store_idx)
- {
- return backEnd->write(req, data, store_idx);
- }
-
- void prefetch(Addr addr, unsigned flags)
- {
- // need to do this...
- }
-
- void writeHint(Addr addr, int size, unsigned flags)
- {
- // need to do this...
- }
-
- Fault copySrcTranslate(Addr src);
-
- Fault copy(Addr dest);
-
- InstSeqNum globalSeqNum;
-
- public:
- void squashFromXC();
-
- // @todo: This can be a useful debug function. Implement it.
- void dumpInsts() { frontEnd->dumpInsts(); }
-
-#if FULL_SYSTEM
- Fault hwrei();
- int readIntrFlag() { return thread.regs.intrflag; }
- void setIntrFlag(int val) { thread.regs.intrflag = val; }
- bool inPalMode() { return AlphaISA::PcPAL(thread.PC); }
- bool inPalMode(Addr pc) { return AlphaISA::PcPAL(pc); }
- bool simPalCheck(int palFunc);
- void processInterrupts();
-#else
- void syscall();
- void setSyscallReturn(SyscallReturn return_value, int tid);
-#endif
-
- ExecContext *xcBase() { return xcProxy; }
-
- bool decoupledFrontEnd;
- struct CommStruct {
- InstSeqNum doneSeqNum;
- InstSeqNum nonSpecSeqNum;
- bool uncached;
- unsigned lqIdx;
-
- bool stall;
- };
- TimeBuffer<CommStruct> comm;
-
- bool lockFlag;
-
- Stats::Scalar<> quiesceCycles;
-
- Checker<DynInstPtr> *checker;
-};
-
-#endif // __CPU_OZONE_CPU_HH__
diff --git a/cpu/ozone/cpu_builder.cc b/cpu/ozone/cpu_builder.cc
deleted file mode 100644
index 1ab7a4c29..000000000
--- a/cpu/ozone/cpu_builder.cc
+++ /dev/null
@@ -1,861 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <string>
-
-#include "cpu/checker/cpu.hh"
-#include "cpu/inst_seq.hh"
-#include "cpu/ozone/cpu.hh"
-#include "cpu/ozone/ozone_impl.hh"
-#include "cpu/ozone/simple_impl.hh"
-#include "cpu/ozone/simple_params.hh"
-#include "mem/cache/base_cache.hh"
-#include "sim/builder.hh"
-#include "sim/process.hh"
-#include "sim/sim_object.hh"
-
-class DerivOzoneCPU : public OzoneCPU<OzoneImpl>
-{
- public:
- DerivOzoneCPU(SimpleParams *p)
- : OzoneCPU<OzoneImpl>(p)
- { }
-};
-
-class SimpleOzoneCPU : public OzoneCPU<SimpleImpl>
-{
- public:
- SimpleOzoneCPU(SimpleParams *p)
- : OzoneCPU<SimpleImpl>(p)
- { }
-};
-
-
-////////////////////////////////////////////////////////////////////////
-//
-// OzoneCPU Simulation Object
-//
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivOzoneCPU)
-
- Param<int> clock;
- Param<int> numThreads;
-
-#if FULL_SYSTEM
-SimObjectParam<System *> system;
-Param<int> cpu_id;
-SimObjectParam<AlphaITB *> itb;
-SimObjectParam<AlphaDTB *> dtb;
-#else
-SimObjectVectorParam<Process *> workload;
-//SimObjectParam<PageTable *> page_table;
-#endif // FULL_SYSTEM
-
-SimObjectParam<FunctionalMemory *> mem;
-
-SimObjectParam<BaseCPU *> checker;
-
-Param<Counter> max_insts_any_thread;
-Param<Counter> max_insts_all_threads;
-Param<Counter> max_loads_any_thread;
-Param<Counter> max_loads_all_threads;
-
-SimObjectParam<BaseCache *> icache;
-SimObjectParam<BaseCache *> dcache;
-
-Param<unsigned> cachePorts;
-Param<unsigned> width;
-Param<unsigned> frontEndWidth;
-Param<unsigned> backEndWidth;
-Param<unsigned> backEndSquashLatency;
-Param<unsigned> backEndLatency;
-Param<unsigned> maxInstBufferSize;
-Param<unsigned> numPhysicalRegs;
-Param<unsigned> maxOutstandingMemOps;
-
-Param<unsigned> decodeToFetchDelay;
-Param<unsigned> renameToFetchDelay;
-Param<unsigned> iewToFetchDelay;
-Param<unsigned> commitToFetchDelay;
-Param<unsigned> fetchWidth;
-
-Param<unsigned> renameToDecodeDelay;
-Param<unsigned> iewToDecodeDelay;
-Param<unsigned> commitToDecodeDelay;
-Param<unsigned> fetchToDecodeDelay;
-Param<unsigned> decodeWidth;
-
-Param<unsigned> iewToRenameDelay;
-Param<unsigned> commitToRenameDelay;
-Param<unsigned> decodeToRenameDelay;
-Param<unsigned> renameWidth;
-
-Param<unsigned> commitToIEWDelay;
-Param<unsigned> renameToIEWDelay;
-Param<unsigned> issueToExecuteDelay;
-Param<unsigned> issueWidth;
-Param<unsigned> executeWidth;
-Param<unsigned> executeIntWidth;
-Param<unsigned> executeFloatWidth;
-Param<unsigned> executeBranchWidth;
-Param<unsigned> executeMemoryWidth;
-
-Param<unsigned> iewToCommitDelay;
-Param<unsigned> renameToROBDelay;
-Param<unsigned> commitWidth;
-Param<unsigned> squashWidth;
-
-Param<std::string> predType;
-Param<unsigned> localPredictorSize;
-Param<unsigned> localCtrBits;
-Param<unsigned> localHistoryTableSize;
-Param<unsigned> localHistoryBits;
-Param<unsigned> globalPredictorSize;
-Param<unsigned> globalCtrBits;
-Param<unsigned> globalHistoryBits;
-Param<unsigned> choicePredictorSize;
-Param<unsigned> choiceCtrBits;
-
-Param<unsigned> BTBEntries;
-Param<unsigned> BTBTagSize;
-
-Param<unsigned> RASSize;
-
-Param<unsigned> LQEntries;
-Param<unsigned> SQEntries;
-Param<unsigned> LFSTSize;
-Param<unsigned> SSITSize;
-
-Param<unsigned> numPhysIntRegs;
-Param<unsigned> numPhysFloatRegs;
-Param<unsigned> numIQEntries;
-Param<unsigned> numROBEntries;
-
-Param<bool> decoupledFrontEnd;
-Param<int> dispatchWidth;
-Param<int> wbWidth;
-
-Param<unsigned> smtNumFetchingThreads;
-Param<std::string> smtFetchPolicy;
-Param<std::string> smtLSQPolicy;
-Param<unsigned> smtLSQThreshold;
-Param<std::string> smtIQPolicy;
-Param<unsigned> smtIQThreshold;
-Param<std::string> smtROBPolicy;
-Param<unsigned> smtROBThreshold;
-Param<std::string> smtCommitPolicy;
-
-Param<unsigned> instShiftAmt;
-
-Param<bool> defer_registration;
-
-Param<bool> function_trace;
-Param<Tick> function_trace_start;
-
-END_DECLARE_SIM_OBJECT_PARAMS(DerivOzoneCPU)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(DerivOzoneCPU)
-
- INIT_PARAM(clock, "clock speed"),
- INIT_PARAM(numThreads, "number of HW thread contexts"),
-
-#if FULL_SYSTEM
- INIT_PARAM(system, "System object"),
- INIT_PARAM(cpu_id, "processor ID"),
- INIT_PARAM(itb, "Instruction translation buffer"),
- INIT_PARAM(dtb, "Data translation buffer"),
-#else
- INIT_PARAM(workload, "Processes to run"),
-// INIT_PARAM(page_table, "Page table"),
-#endif // FULL_SYSTEM
-
- INIT_PARAM_DFLT(mem, "Memory", NULL),
-
- INIT_PARAM_DFLT(checker, "Checker CPU", NULL),
-
- INIT_PARAM_DFLT(max_insts_any_thread,
- "Terminate when any thread reaches this inst count",
- 0),
- INIT_PARAM_DFLT(max_insts_all_threads,
- "Terminate when all threads have reached"
- "this inst count",
- 0),
- INIT_PARAM_DFLT(max_loads_any_thread,
- "Terminate when any thread reaches this load count",
- 0),
- INIT_PARAM_DFLT(max_loads_all_threads,
- "Terminate when all threads have reached this load"
- "count",
- 0),
-
- INIT_PARAM_DFLT(icache, "L1 instruction cache", NULL),
- INIT_PARAM_DFLT(dcache, "L1 data cache", NULL),
-
- INIT_PARAM_DFLT(cachePorts, "Cache Ports", 200),
- INIT_PARAM_DFLT(width, "Width", 1),
- INIT_PARAM_DFLT(frontEndWidth, "Front end width", 1),
- INIT_PARAM_DFLT(backEndWidth, "Back end width", 1),
- INIT_PARAM_DFLT(backEndSquashLatency, "Back end squash latency", 1),
- INIT_PARAM_DFLT(backEndLatency, "Back end latency", 1),
- INIT_PARAM_DFLT(maxInstBufferSize, "Maximum instruction buffer size", 16),
- INIT_PARAM(numPhysicalRegs, "Number of physical registers"),
- INIT_PARAM_DFLT(maxOutstandingMemOps, "Maximum outstanding memory operations", 4),
-
- INIT_PARAM(decodeToFetchDelay, "Decode to fetch delay"),
- INIT_PARAM(renameToFetchDelay, "Rename to fetch delay"),
- INIT_PARAM(iewToFetchDelay, "Issue/Execute/Writeback to fetch"
- "delay"),
- INIT_PARAM(commitToFetchDelay, "Commit to fetch delay"),
- INIT_PARAM(fetchWidth, "Fetch width"),
- INIT_PARAM(renameToDecodeDelay, "Rename to decode delay"),
- INIT_PARAM(iewToDecodeDelay, "Issue/Execute/Writeback to decode"
- "delay"),
- INIT_PARAM(commitToDecodeDelay, "Commit to decode delay"),
- INIT_PARAM(fetchToDecodeDelay, "Fetch to decode delay"),
- INIT_PARAM(decodeWidth, "Decode width"),
-
- INIT_PARAM(iewToRenameDelay, "Issue/Execute/Writeback to rename"
- "delay"),
- INIT_PARAM(commitToRenameDelay, "Commit to rename delay"),
- INIT_PARAM(decodeToRenameDelay, "Decode to rename delay"),
- INIT_PARAM(renameWidth, "Rename width"),
-
- INIT_PARAM(commitToIEWDelay, "Commit to "
- "Issue/Execute/Writeback delay"),
- INIT_PARAM(renameToIEWDelay, "Rename to "
- "Issue/Execute/Writeback delay"),
- INIT_PARAM(issueToExecuteDelay, "Issue to execute delay (internal"
- "to the IEW stage)"),
- INIT_PARAM(issueWidth, "Issue width"),
- INIT_PARAM(executeWidth, "Execute width"),
- INIT_PARAM(executeIntWidth, "Integer execute width"),
- INIT_PARAM(executeFloatWidth, "Floating point execute width"),
- INIT_PARAM(executeBranchWidth, "Branch execute width"),
- INIT_PARAM(executeMemoryWidth, "Memory execute width"),
-
- INIT_PARAM(iewToCommitDelay, "Issue/Execute/Writeback to commit "
- "delay"),
- INIT_PARAM(renameToROBDelay, "Rename to reorder buffer delay"),
- INIT_PARAM(commitWidth, "Commit width"),
- INIT_PARAM(squashWidth, "Squash width"),
-
- INIT_PARAM(predType, "Type of branch predictor ('local', 'tournament')"),
- INIT_PARAM(localPredictorSize, "Size of local predictor"),
- INIT_PARAM(localCtrBits, "Bits per counter"),
- INIT_PARAM(localHistoryTableSize, "Size of local history table"),
- INIT_PARAM(localHistoryBits, "Bits for the local history"),
- INIT_PARAM(globalPredictorSize, "Size of global predictor"),
- INIT_PARAM(globalCtrBits, "Bits per counter"),
- INIT_PARAM(globalHistoryBits, "Bits of history"),
- INIT_PARAM(choicePredictorSize, "Size of choice predictor"),
- INIT_PARAM(choiceCtrBits, "Bits of choice counters"),
-
- INIT_PARAM(BTBEntries, "Number of BTB entries"),
- INIT_PARAM(BTBTagSize, "Size of the BTB tags, in bits"),
-
- INIT_PARAM(RASSize, "RAS size"),
-
- INIT_PARAM(LQEntries, "Number of load queue entries"),
- INIT_PARAM(SQEntries, "Number of store queue entries"),
- INIT_PARAM(LFSTSize, "Last fetched store table size"),
- INIT_PARAM(SSITSize, "Store set ID table size"),
-
- INIT_PARAM(numPhysIntRegs, "Number of physical integer registers"),
- INIT_PARAM(numPhysFloatRegs, "Number of physical floating point "
- "registers"),
- INIT_PARAM(numIQEntries, "Number of instruction queue entries"),
- INIT_PARAM(numROBEntries, "Number of reorder buffer entries"),
-
- INIT_PARAM_DFLT(decoupledFrontEnd, "Decoupled front end", true),
- INIT_PARAM_DFLT(dispatchWidth, "Dispatch width", 0),
- INIT_PARAM_DFLT(wbWidth, "Writeback width", 0),
-
- INIT_PARAM_DFLT(smtNumFetchingThreads, "SMT Number of Fetching Threads", 1),
- INIT_PARAM_DFLT(smtFetchPolicy, "SMT Fetch Policy", "SingleThread"),
- INIT_PARAM_DFLT(smtLSQPolicy, "SMT LSQ Sharing Policy", "Partitioned"),
- INIT_PARAM_DFLT(smtLSQThreshold,"SMT LSQ Threshold", 100),
- INIT_PARAM_DFLT(smtIQPolicy, "SMT IQ Policy", "Partitioned"),
- INIT_PARAM_DFLT(smtIQThreshold, "SMT IQ Threshold", 100),
- INIT_PARAM_DFLT(smtROBPolicy, "SMT ROB Sharing Policy", "Partitioned"),
- INIT_PARAM_DFLT(smtROBThreshold,"SMT ROB Threshold", 100),
- INIT_PARAM_DFLT(smtCommitPolicy,"SMT Commit Fetch Policy", "RoundRobin"),
-
- INIT_PARAM(instShiftAmt, "Number of bits to shift instructions by"),
- INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
-
- INIT_PARAM(function_trace, "Enable function trace"),
- INIT_PARAM(function_trace_start, "Cycle to start function trace")
-
-END_INIT_SIM_OBJECT_PARAMS(DerivOzoneCPU)
-
-CREATE_SIM_OBJECT(DerivOzoneCPU)
-{
- DerivOzoneCPU *cpu;
-
-#if FULL_SYSTEM
- // Full-system only supports a single thread for the moment.
- int actual_num_threads = 1;
-#else
- // In non-full-system mode, we infer the number of threads from
- // the workload if it's not explicitly specified.
- int actual_num_threads =
- numThreads.isValid() ? numThreads : workload.size();
-
- if (workload.size() == 0) {
- fatal("Must specify at least one workload!");
- }
-
-#endif
-
- SimpleParams *params = new SimpleParams;
-
- params->clock = clock;
-
- params->name = getInstanceName();
- params->numberOfThreads = actual_num_threads;
-
-#if FULL_SYSTEM
- params->system = system;
- params->cpu_id = cpu_id;
- params->itb = itb;
- params->dtb = dtb;
-#else
- params->workload = workload;
-// params->pTable = page_table;
-#endif // FULL_SYSTEM
-
- params->mem = mem;
- params->checker = checker;
- params->max_insts_any_thread = max_insts_any_thread;
- params->max_insts_all_threads = max_insts_all_threads;
- params->max_loads_any_thread = max_loads_any_thread;
- params->max_loads_all_threads = max_loads_all_threads;
-
- //
- // Caches
- //
- params->icacheInterface = icache ? icache->getInterface() : NULL;
- params->dcacheInterface = dcache ? dcache->getInterface() : NULL;
- params->cachePorts = cachePorts;
-
- params->width = width;
- params->frontEndWidth = frontEndWidth;
- params->backEndWidth = backEndWidth;
- params->backEndSquashLatency = backEndSquashLatency;
- params->backEndLatency = backEndLatency;
- params->maxInstBufferSize = maxInstBufferSize;
- params->numPhysicalRegs = numPhysIntRegs + numPhysFloatRegs;
- params->maxOutstandingMemOps = maxOutstandingMemOps;
-
- params->decodeToFetchDelay = decodeToFetchDelay;
- params->renameToFetchDelay = renameToFetchDelay;
- params->iewToFetchDelay = iewToFetchDelay;
- params->commitToFetchDelay = commitToFetchDelay;
- params->fetchWidth = fetchWidth;
-
- params->renameToDecodeDelay = renameToDecodeDelay;
- params->iewToDecodeDelay = iewToDecodeDelay;
- params->commitToDecodeDelay = commitToDecodeDelay;
- params->fetchToDecodeDelay = fetchToDecodeDelay;
- params->decodeWidth = decodeWidth;
-
- params->iewToRenameDelay = iewToRenameDelay;
- params->commitToRenameDelay = commitToRenameDelay;
- params->decodeToRenameDelay = decodeToRenameDelay;
- params->renameWidth = renameWidth;
-
- params->commitToIEWDelay = commitToIEWDelay;
- params->renameToIEWDelay = renameToIEWDelay;
- params->issueToExecuteDelay = issueToExecuteDelay;
- params->issueWidth = issueWidth;
- params->executeWidth = executeWidth;
- params->executeIntWidth = executeIntWidth;
- params->executeFloatWidth = executeFloatWidth;
- params->executeBranchWidth = executeBranchWidth;
- params->executeMemoryWidth = executeMemoryWidth;
-
- params->iewToCommitDelay = iewToCommitDelay;
- params->renameToROBDelay = renameToROBDelay;
- params->commitWidth = commitWidth;
- params->squashWidth = squashWidth;
-
- params->predType = predType;
- params->localPredictorSize = localPredictorSize;
- params->localCtrBits = localCtrBits;
- params->localHistoryTableSize = localHistoryTableSize;
- params->localHistoryBits = localHistoryBits;
- params->globalPredictorSize = globalPredictorSize;
- params->globalCtrBits = globalCtrBits;
- params->globalHistoryBits = globalHistoryBits;
- params->choicePredictorSize = choicePredictorSize;
- params->choiceCtrBits = choiceCtrBits;
-
- params->BTBEntries = BTBEntries;
- params->BTBTagSize = BTBTagSize;
-
- params->RASSize = RASSize;
-
- params->LQEntries = LQEntries;
- params->SQEntries = SQEntries;
-
- params->SSITSize = SSITSize;
- params->LFSTSize = LFSTSize;
-
- params->numPhysIntRegs = numPhysIntRegs;
- params->numPhysFloatRegs = numPhysFloatRegs;
- params->numIQEntries = numIQEntries;
- params->numROBEntries = numROBEntries;
-
- params->decoupledFrontEnd = decoupledFrontEnd;
- params->dispatchWidth = dispatchWidth;
- params->wbWidth = wbWidth;
-
- params->smtNumFetchingThreads = smtNumFetchingThreads;
- params->smtFetchPolicy = smtFetchPolicy;
- params->smtIQPolicy = smtIQPolicy;
- params->smtLSQPolicy = smtLSQPolicy;
- params->smtLSQThreshold = smtLSQThreshold;
- params->smtROBPolicy = smtROBPolicy;
- params->smtROBThreshold = smtROBThreshold;
- params->smtCommitPolicy = smtCommitPolicy;
-
- params->instShiftAmt = 2;
-
- params->deferRegistration = defer_registration;
-
- params->functionTrace = function_trace;
- params->functionTraceStart = function_trace_start;
-
- cpu = new DerivOzoneCPU(params);
-
- return cpu;
-}
-
-REGISTER_SIM_OBJECT("DerivOzoneCPU", DerivOzoneCPU)
-
-
-
-////////////////////////////////////////////////////////////////////////
-//
-// OzoneCPU Simulation Object
-//
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleOzoneCPU)
-
- Param<int> clock;
- Param<int> numThreads;
-
-#if FULL_SYSTEM
-SimObjectParam<System *> system;
-Param<int> cpu_id;
-SimObjectParam<AlphaITB *> itb;
-SimObjectParam<AlphaDTB *> dtb;
-#else
-SimObjectVectorParam<Process *> workload;
-//SimObjectParam<PageTable *> page_table;
-#endif // FULL_SYSTEM
-
-SimObjectParam<FunctionalMemory *> mem;
-
-SimObjectParam<BaseCPU *> checker;
-
-Param<Counter> max_insts_any_thread;
-Param<Counter> max_insts_all_threads;
-Param<Counter> max_loads_any_thread;
-Param<Counter> max_loads_all_threads;
-
-SimObjectParam<BaseCache *> icache;
-SimObjectParam<BaseCache *> dcache;
-
-Param<unsigned> cachePorts;
-Param<unsigned> width;
-Param<unsigned> frontEndWidth;
-Param<unsigned> backEndWidth;
-Param<unsigned> backEndSquashLatency;
-Param<unsigned> backEndLatency;
-Param<unsigned> maxInstBufferSize;
-Param<unsigned> numPhysicalRegs;
-
-Param<unsigned> decodeToFetchDelay;
-Param<unsigned> renameToFetchDelay;
-Param<unsigned> iewToFetchDelay;
-Param<unsigned> commitToFetchDelay;
-Param<unsigned> fetchWidth;
-
-Param<unsigned> renameToDecodeDelay;
-Param<unsigned> iewToDecodeDelay;
-Param<unsigned> commitToDecodeDelay;
-Param<unsigned> fetchToDecodeDelay;
-Param<unsigned> decodeWidth;
-
-Param<unsigned> iewToRenameDelay;
-Param<unsigned> commitToRenameDelay;
-Param<unsigned> decodeToRenameDelay;
-Param<unsigned> renameWidth;
-
-Param<unsigned> commitToIEWDelay;
-Param<unsigned> renameToIEWDelay;
-Param<unsigned> issueToExecuteDelay;
-Param<unsigned> issueWidth;
-Param<unsigned> executeWidth;
-Param<unsigned> executeIntWidth;
-Param<unsigned> executeFloatWidth;
-Param<unsigned> executeBranchWidth;
-Param<unsigned> executeMemoryWidth;
-
-Param<unsigned> iewToCommitDelay;
-Param<unsigned> renameToROBDelay;
-Param<unsigned> commitWidth;
-Param<unsigned> squashWidth;
-
-Param<std::string> predType;
-Param<unsigned> localPredictorSize;
-Param<unsigned> localCtrBits;
-Param<unsigned> localHistoryTableSize;
-Param<unsigned> localHistoryBits;
-Param<unsigned> globalPredictorSize;
-Param<unsigned> globalCtrBits;
-Param<unsigned> globalHistoryBits;
-Param<unsigned> choicePredictorSize;
-Param<unsigned> choiceCtrBits;
-
-Param<unsigned> BTBEntries;
-Param<unsigned> BTBTagSize;
-
-Param<unsigned> RASSize;
-
-Param<unsigned> LQEntries;
-Param<unsigned> SQEntries;
-Param<unsigned> LFSTSize;
-Param<unsigned> SSITSize;
-
-Param<unsigned> numPhysIntRegs;
-Param<unsigned> numPhysFloatRegs;
-Param<unsigned> numIQEntries;
-Param<unsigned> numROBEntries;
-
-Param<bool> decoupledFrontEnd;
-Param<int> dispatchWidth;
-Param<int> wbWidth;
-
-Param<unsigned> smtNumFetchingThreads;
-Param<std::string> smtFetchPolicy;
-Param<std::string> smtLSQPolicy;
-Param<unsigned> smtLSQThreshold;
-Param<std::string> smtIQPolicy;
-Param<unsigned> smtIQThreshold;
-Param<std::string> smtROBPolicy;
-Param<unsigned> smtROBThreshold;
-Param<std::string> smtCommitPolicy;
-
-Param<unsigned> instShiftAmt;
-
-Param<bool> defer_registration;
-
-Param<bool> function_trace;
-Param<Tick> function_trace_start;
-
-END_DECLARE_SIM_OBJECT_PARAMS(SimpleOzoneCPU)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleOzoneCPU)
-
- INIT_PARAM(clock, "clock speed"),
- INIT_PARAM(numThreads, "number of HW thread contexts"),
-
-#if FULL_SYSTEM
- INIT_PARAM(system, "System object"),
- INIT_PARAM(cpu_id, "processor ID"),
- INIT_PARAM(itb, "Instruction translation buffer"),
- INIT_PARAM(dtb, "Data translation buffer"),
-#else
- INIT_PARAM(workload, "Processes to run"),
-// INIT_PARAM(page_table, "Page table"),
-#endif // FULL_SYSTEM
-
- INIT_PARAM_DFLT(mem, "Memory", NULL),
-
- INIT_PARAM_DFLT(checker, "Checker CPU", NULL),
-
- INIT_PARAM_DFLT(max_insts_any_thread,
- "Terminate when any thread reaches this inst count",
- 0),
- INIT_PARAM_DFLT(max_insts_all_threads,
- "Terminate when all threads have reached"
- "this inst count",
- 0),
- INIT_PARAM_DFLT(max_loads_any_thread,
- "Terminate when any thread reaches this load count",
- 0),
- INIT_PARAM_DFLT(max_loads_all_threads,
- "Terminate when all threads have reached this load"
- "count",
- 0),
-
- INIT_PARAM_DFLT(icache, "L1 instruction cache", NULL),
- INIT_PARAM_DFLT(dcache, "L1 data cache", NULL),
-
- INIT_PARAM_DFLT(cachePorts, "Cache Ports", 200),
- INIT_PARAM_DFLT(width, "Width", 1),
- INIT_PARAM_DFLT(frontEndWidth, "Front end width", 1),
- INIT_PARAM_DFLT(backEndWidth, "Back end width", 1),
- INIT_PARAM_DFLT(backEndSquashLatency, "Back end squash latency", 1),
- INIT_PARAM_DFLT(backEndLatency, "Back end latency", 1),
- INIT_PARAM_DFLT(maxInstBufferSize, "Maximum instruction buffer size", 16),
- INIT_PARAM(numPhysicalRegs, "Number of physical registers"),
-
- INIT_PARAM(decodeToFetchDelay, "Decode to fetch delay"),
- INIT_PARAM(renameToFetchDelay, "Rename to fetch delay"),
- INIT_PARAM(iewToFetchDelay, "Issue/Execute/Writeback to fetch"
- "delay"),
- INIT_PARAM(commitToFetchDelay, "Commit to fetch delay"),
- INIT_PARAM(fetchWidth, "Fetch width"),
- INIT_PARAM(renameToDecodeDelay, "Rename to decode delay"),
- INIT_PARAM(iewToDecodeDelay, "Issue/Execute/Writeback to decode"
- "delay"),
- INIT_PARAM(commitToDecodeDelay, "Commit to decode delay"),
- INIT_PARAM(fetchToDecodeDelay, "Fetch to decode delay"),
- INIT_PARAM(decodeWidth, "Decode width"),
-
- INIT_PARAM(iewToRenameDelay, "Issue/Execute/Writeback to rename"
- "delay"),
- INIT_PARAM(commitToRenameDelay, "Commit to rename delay"),
- INIT_PARAM(decodeToRenameDelay, "Decode to rename delay"),
- INIT_PARAM(renameWidth, "Rename width"),
-
- INIT_PARAM(commitToIEWDelay, "Commit to "
- "Issue/Execute/Writeback delay"),
- INIT_PARAM(renameToIEWDelay, "Rename to "
- "Issue/Execute/Writeback delay"),
- INIT_PARAM(issueToExecuteDelay, "Issue to execute delay (internal"
- "to the IEW stage)"),
- INIT_PARAM(issueWidth, "Issue width"),
- INIT_PARAM(executeWidth, "Execute width"),
- INIT_PARAM(executeIntWidth, "Integer execute width"),
- INIT_PARAM(executeFloatWidth, "Floating point execute width"),
- INIT_PARAM(executeBranchWidth, "Branch execute width"),
- INIT_PARAM(executeMemoryWidth, "Memory execute width"),
-
- INIT_PARAM(iewToCommitDelay, "Issue/Execute/Writeback to commit "
- "delay"),
- INIT_PARAM(renameToROBDelay, "Rename to reorder buffer delay"),
- INIT_PARAM(commitWidth, "Commit width"),
- INIT_PARAM(squashWidth, "Squash width"),
-
- INIT_PARAM(predType, "Type of branch predictor ('local', 'tournament')"),
- INIT_PARAM(localPredictorSize, "Size of local predictor"),
- INIT_PARAM(localCtrBits, "Bits per counter"),
- INIT_PARAM(localHistoryTableSize, "Size of local history table"),
- INIT_PARAM(localHistoryBits, "Bits for the local history"),
- INIT_PARAM(globalPredictorSize, "Size of global predictor"),
- INIT_PARAM(globalCtrBits, "Bits per counter"),
- INIT_PARAM(globalHistoryBits, "Bits of history"),
- INIT_PARAM(choicePredictorSize, "Size of choice predictor"),
- INIT_PARAM(choiceCtrBits, "Bits of choice counters"),
-
- INIT_PARAM(BTBEntries, "Number of BTB entries"),
- INIT_PARAM(BTBTagSize, "Size of the BTB tags, in bits"),
-
- INIT_PARAM(RASSize, "RAS size"),
-
- INIT_PARAM(LQEntries, "Number of load queue entries"),
- INIT_PARAM(SQEntries, "Number of store queue entries"),
- INIT_PARAM(LFSTSize, "Last fetched store table size"),
- INIT_PARAM(SSITSize, "Store set ID table size"),
-
- INIT_PARAM(numPhysIntRegs, "Number of physical integer registers"),
- INIT_PARAM(numPhysFloatRegs, "Number of physical floating point "
- "registers"),
- INIT_PARAM(numIQEntries, "Number of instruction queue entries"),
- INIT_PARAM(numROBEntries, "Number of reorder buffer entries"),
-
- INIT_PARAM_DFLT(decoupledFrontEnd, "Decoupled front end", true),
- INIT_PARAM_DFLT(dispatchWidth, "Dispatch width", 0),
- INIT_PARAM_DFLT(wbWidth, "Writeback width", 0),
-
- INIT_PARAM_DFLT(smtNumFetchingThreads, "SMT Number of Fetching Threads", 1),
- INIT_PARAM_DFLT(smtFetchPolicy, "SMT Fetch Policy", "SingleThread"),
- INIT_PARAM_DFLT(smtLSQPolicy, "SMT LSQ Sharing Policy", "Partitioned"),
- INIT_PARAM_DFLT(smtLSQThreshold,"SMT LSQ Threshold", 100),
- INIT_PARAM_DFLT(smtIQPolicy, "SMT IQ Policy", "Partitioned"),
- INIT_PARAM_DFLT(smtIQThreshold, "SMT IQ Threshold", 100),
- INIT_PARAM_DFLT(smtROBPolicy, "SMT ROB Sharing Policy", "Partitioned"),
- INIT_PARAM_DFLT(smtROBThreshold,"SMT ROB Threshold", 100),
- INIT_PARAM_DFLT(smtCommitPolicy,"SMT Commit Fetch Policy", "RoundRobin"),
-
- INIT_PARAM(instShiftAmt, "Number of bits to shift instructions by"),
- INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
-
- INIT_PARAM(function_trace, "Enable function trace"),
- INIT_PARAM(function_trace_start, "Cycle to start function trace")
-
-END_INIT_SIM_OBJECT_PARAMS(SimpleOzoneCPU)
-
-CREATE_SIM_OBJECT(SimpleOzoneCPU)
-{
- SimpleOzoneCPU *cpu;
-
-#if FULL_SYSTEM
- // Full-system only supports a single thread for the moment.
- int actual_num_threads = 1;
-#else
- // In non-full-system mode, we infer the number of threads from
- // the workload if it's not explicitly specified.
- int actual_num_threads =
- numThreads.isValid() ? numThreads : workload.size();
-
- if (workload.size() == 0) {
- fatal("Must specify at least one workload!");
- }
-
-#endif
-
- SimpleParams *params = new SimpleParams;
-
- params->clock = clock;
-
- params->name = getInstanceName();
- params->numberOfThreads = actual_num_threads;
-
-#if FULL_SYSTEM
- params->system = system;
- params->cpu_id = cpu_id;
- params->itb = itb;
- params->dtb = dtb;
-#else
- params->workload = workload;
-// params->pTable = page_table;
-#endif // FULL_SYSTEM
-
- params->mem = mem;
- params->checker = checker;
- params->max_insts_any_thread = max_insts_any_thread;
- params->max_insts_all_threads = max_insts_all_threads;
- params->max_loads_any_thread = max_loads_any_thread;
- params->max_loads_all_threads = max_loads_all_threads;
-
- //
- // Caches
- //
- params->icacheInterface = icache ? icache->getInterface() : NULL;
- params->dcacheInterface = dcache ? dcache->getInterface() : NULL;
- params->cachePorts = cachePorts;
-
- params->width = width;
- params->frontEndWidth = frontEndWidth;
- params->backEndWidth = backEndWidth;
- params->backEndSquashLatency = backEndSquashLatency;
- params->backEndLatency = backEndLatency;
- params->maxInstBufferSize = maxInstBufferSize;
- params->numPhysicalRegs = numPhysIntRegs + numPhysFloatRegs;
-
- params->decodeToFetchDelay = decodeToFetchDelay;
- params->renameToFetchDelay = renameToFetchDelay;
- params->iewToFetchDelay = iewToFetchDelay;
- params->commitToFetchDelay = commitToFetchDelay;
- params->fetchWidth = fetchWidth;
-
- params->renameToDecodeDelay = renameToDecodeDelay;
- params->iewToDecodeDelay = iewToDecodeDelay;
- params->commitToDecodeDelay = commitToDecodeDelay;
- params->fetchToDecodeDelay = fetchToDecodeDelay;
- params->decodeWidth = decodeWidth;
-
- params->iewToRenameDelay = iewToRenameDelay;
- params->commitToRenameDelay = commitToRenameDelay;
- params->decodeToRenameDelay = decodeToRenameDelay;
- params->renameWidth = renameWidth;
-
- params->commitToIEWDelay = commitToIEWDelay;
- params->renameToIEWDelay = renameToIEWDelay;
- params->issueToExecuteDelay = issueToExecuteDelay;
- params->issueWidth = issueWidth;
- params->executeWidth = executeWidth;
- params->executeIntWidth = executeIntWidth;
- params->executeFloatWidth = executeFloatWidth;
- params->executeBranchWidth = executeBranchWidth;
- params->executeMemoryWidth = executeMemoryWidth;
-
- params->iewToCommitDelay = iewToCommitDelay;
- params->renameToROBDelay = renameToROBDelay;
- params->commitWidth = commitWidth;
- params->squashWidth = squashWidth;
-
- params->predType = predType;
- params->localPredictorSize = localPredictorSize;
- params->localCtrBits = localCtrBits;
- params->localHistoryTableSize = localHistoryTableSize;
- params->localHistoryBits = localHistoryBits;
- params->globalPredictorSize = globalPredictorSize;
- params->globalCtrBits = globalCtrBits;
- params->globalHistoryBits = globalHistoryBits;
- params->choicePredictorSize = choicePredictorSize;
- params->choiceCtrBits = choiceCtrBits;
-
- params->BTBEntries = BTBEntries;
- params->BTBTagSize = BTBTagSize;
-
- params->RASSize = RASSize;
-
- params->LQEntries = LQEntries;
- params->SQEntries = SQEntries;
-
- params->SSITSize = SSITSize;
- params->LFSTSize = LFSTSize;
-
- params->numPhysIntRegs = numPhysIntRegs;
- params->numPhysFloatRegs = numPhysFloatRegs;
- params->numIQEntries = numIQEntries;
- params->numROBEntries = numROBEntries;
-
- params->decoupledFrontEnd = decoupledFrontEnd;
- params->dispatchWidth = dispatchWidth;
- params->wbWidth = wbWidth;
-
- params->smtNumFetchingThreads = smtNumFetchingThreads;
- params->smtFetchPolicy = smtFetchPolicy;
- params->smtIQPolicy = smtIQPolicy;
- params->smtLSQPolicy = smtLSQPolicy;
- params->smtLSQThreshold = smtLSQThreshold;
- params->smtROBPolicy = smtROBPolicy;
- params->smtROBThreshold = smtROBThreshold;
- params->smtCommitPolicy = smtCommitPolicy;
-
- params->instShiftAmt = 2;
-
- params->deferRegistration = defer_registration;
-
- params->functionTrace = function_trace;
- params->functionTraceStart = function_trace_start;
-
- cpu = new SimpleOzoneCPU(params);
-
- return cpu;
-}
-
-REGISTER_SIM_OBJECT("SimpleOzoneCPU", SimpleOzoneCPU)
-
diff --git a/cpu/ozone/cpu_impl.hh b/cpu/ozone/cpu_impl.hh
deleted file mode 100644
index 5675da3a8..000000000
--- a/cpu/ozone/cpu_impl.hh
+++ /dev/null
@@ -1,1049 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-//#include <cstdio>
-//#include <cstdlib>
-
-#include "arch/isa_traits.hh" // For MachInst
-#include "base/trace.hh"
-#include "config/full_system.hh"
-#include "cpu/base.hh"
-#include "cpu/checker/exec_context.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/exetrace.hh"
-#include "cpu/ozone/cpu.hh"
-#include "cpu/quiesce_event.hh"
-#include "cpu/static_inst.hh"
-//#include "mem/base_mem.hh"
-#include "mem/mem_interface.hh"
-#include "sim/sim_object.hh"
-#include "sim/stats.hh"
-
-#if FULL_SYSTEM
-#include "arch/faults.hh"
-#include "arch/alpha/osfpal.hh"
-#include "arch/alpha/tlb.hh"
-#include "arch/vtophys.hh"
-#include "base/callback.hh"
-//#include "base/remote_gdb.hh"
-#include "cpu/profile.hh"
-#include "kern/kernel_stats.hh"
-#include "mem/functional/memory_control.hh"
-#include "mem/functional/physical.hh"
-#include "sim/faults.hh"
-#include "sim/sim_events.hh"
-#include "sim/sim_exit.hh"
-#include "sim/system.hh"
-#else // !FULL_SYSTEM
-#include "mem/functional/functional.hh"
-#include "sim/process.hh"
-#endif // FULL_SYSTEM
-
-using namespace TheISA;
-
-template <class Impl>
-template<typename T>
-void
-OzoneCPU<Impl>::trace_data(T data) {
- if (traceData) {
- traceData->setData(data);
- }
-}
-
-template <class Impl>
-OzoneCPU<Impl>::TickEvent::TickEvent(OzoneCPU *c, int w)
- : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c), width(w)
-{
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::TickEvent::process()
-{
- cpu->tick();
-}
-
-template <class Impl>
-const char *
-OzoneCPU<Impl>::TickEvent::description()
-{
- return "OzoneCPU tick event";
-}
-
-template <class Impl>
-OzoneCPU<Impl>::OzoneCPU(Params *p)
-#if FULL_SYSTEM
- : BaseCPU(p), thread(this, 0, p->mem), tickEvent(this, p->width),
- mem(p->mem),
-#else
- : BaseCPU(p), thread(this, 0, p->workload[0], 0), tickEvent(this, p->width),
- mem(p->workload[0]->getMemory()),
-#endif
- comm(5, 5)
-{
- frontEnd = new FrontEnd(p);
- backEnd = new BackEnd(p);
-
- _status = Idle;
-
- if (p->checker) {
- BaseCPU *temp_checker = p->checker;
- checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
- checker->setMemory(mem);
-#if FULL_SYSTEM
- checker->setSystem(p->system);
-#endif
- checkerXC = new CheckerExecContext<OzoneXC>(&ozoneXC, checker);
- thread.xcProxy = checkerXC;
- xcProxy = checkerXC;
- } else {
- checker = NULL;
- thread.xcProxy = &ozoneXC;
- xcProxy = &ozoneXC;
- }
-
- ozoneXC.cpu = this;
- ozoneXC.thread = &thread;
-
- thread.inSyscall = false;
-
- thread.setStatus(ExecContext::Suspended);
-#if FULL_SYSTEM
- /***** All thread state stuff *****/
- thread.cpu = this;
- thread.tid = 0;
- thread.mem = p->mem;
-
- thread.quiesceEvent = new EndQuiesceEvent(xcProxy);
-
- system = p->system;
- itb = p->itb;
- dtb = p->dtb;
- memctrl = p->system->memctrl;
- physmem = p->system->physmem;
-
- if (p->profile) {
- thread.profile = new FunctionProfile(p->system->kernelSymtab);
- // @todo: This might be better as an ExecContext instead of OzoneXC
- Callback *cb =
- new MakeCallback<OzoneXC,
- &OzoneXC::dumpFuncProfile>(&ozoneXC);
- registerExitCallback(cb);
- }
-
- // let's fill with a dummy node for now so we don't get a segfault
- // on the first cycle when there's no node available.
- static ProfileNode dummyNode;
- thread.profileNode = &dummyNode;
- thread.profilePC = 3;
-#else
- thread.cpu = this;
- thread.tid = 0;
- thread.process = p->workload[0];
- thread.asid = 0;
-#endif // !FULL_SYSTEM
-
- numInst = 0;
- startNumInst = 0;
-
- execContexts.push_back(xcProxy);
-
- frontEnd->setCPU(this);
- backEnd->setCPU(this);
-
- frontEnd->setXC(xcProxy);
- backEnd->setXC(xcProxy);
-
- frontEnd->setThreadState(&thread);
- backEnd->setThreadState(&thread);
-
- frontEnd->setCommBuffer(&comm);
- backEnd->setCommBuffer(&comm);
-
- frontEnd->setBackEnd(backEnd);
- backEnd->setFrontEnd(frontEnd);
-
- decoupledFrontEnd = p->decoupledFrontEnd;
-
- globalSeqNum = 1;
-
- checkInterrupts = false;
-
- for (int i = 0; i < TheISA::TotalNumRegs; ++i) {
- thread.renameTable[i] = new DynInst(this);
- thread.renameTable[i]->setResultReady();
- }
-
- frontEnd->renameTable.copyFrom(thread.renameTable);
- backEnd->renameTable.copyFrom(thread.renameTable);
-
-#if !FULL_SYSTEM
-// pTable = p->pTable;
-#endif
-
- lockFlag = 0;
-
- DPRINTF(OzoneCPU, "OzoneCPU: Created Ozone cpu object.\n");
-}
-
-template <class Impl>
-OzoneCPU<Impl>::~OzoneCPU()
-{
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::switchOut(Sampler *_sampler)
-{
- sampler = _sampler;
- switchCount = 0;
- // Front end needs state from back end, so switch out the back end first.
- backEnd->switchOut();
- frontEnd->switchOut();
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::signalSwitched()
-{
- if (++switchCount == 2) {
- backEnd->doSwitchOut();
- frontEnd->doSwitchOut();
- if (checker)
- checker->switchOut(sampler);
- _status = SwitchedOut;
- if (tickEvent.scheduled())
- tickEvent.squash();
- sampler->signalSwitched();
- }
- assert(switchCount <= 2);
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
-{
- BaseCPU::takeOverFrom(oldCPU);
-
- backEnd->takeOverFrom();
- frontEnd->takeOverFrom();
- assert(!tickEvent.scheduled());
-
- // @todo: Fix hardcoded number
- // Clear out any old information in time buffer.
- for (int i = 0; i < 6; ++i) {
- comm.advance();
- }
-
- // if any of this CPU's ExecContexts are active, mark the CPU as
- // running and schedule its tick event.
- for (int i = 0; i < execContexts.size(); ++i) {
- ExecContext *xc = execContexts[i];
- if (xc->status() == ExecContext::Active &&
- _status != Running) {
- _status = Running;
- tickEvent.schedule(curTick);
- }
- }
- // Nothing running, change status to reflect that we're no longer
- // switched out.
- if (_status == SwitchedOut) {
- _status = Idle;
- }
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::activateContext(int thread_num, int delay)
-{
- // Eventually change this in SMT.
- assert(thread_num == 0);
-
- assert(_status == Idle);
- notIdleFraction++;
- scheduleTickEvent(delay);
- _status = Running;
- thread._status = ExecContext::Active;
- frontEnd->wakeFromQuiesce();
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::suspendContext(int thread_num)
-{
- // Eventually change this in SMT.
- assert(thread_num == 0);
- // @todo: Figure out how to initially set the status properly so
- // this is running.
-// assert(_status == Running);
- notIdleFraction--;
- unscheduleTickEvent();
- _status = Idle;
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::deallocateContext(int thread_num)
-{
- // for now, these are equivalent
- suspendContext(thread_num);
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::haltContext(int thread_num)
-{
- // for now, these are equivalent
- suspendContext(thread_num);
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::regStats()
-{
- using namespace Stats;
-
- BaseCPU::regStats();
-
- thread.numInsts
- .name(name() + ".num_insts")
- .desc("Number of instructions executed")
- ;
-
- thread.numMemRefs
- .name(name() + ".num_refs")
- .desc("Number of memory references")
- ;
-
- notIdleFraction
- .name(name() + ".not_idle_fraction")
- .desc("Percentage of non-idle cycles")
- ;
-
- idleFraction
- .name(name() + ".idle_fraction")
- .desc("Percentage of idle cycles")
- ;
-
- quiesceCycles
- .name(name() + ".quiesce_cycles")
- .desc("Number of cycles spent in quiesce")
- ;
-
- idleFraction = constant(1.0) - notIdleFraction;
-
- frontEnd->regStats();
- backEnd->regStats();
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::resetStats()
-{
- startNumInst = numInst;
- notIdleFraction = (_status != Idle);
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::init()
-{
- BaseCPU::init();
-
- // Mark this as in syscall so it won't need to squash
- thread.inSyscall = true;
-#if FULL_SYSTEM
- for (int i = 0; i < execContexts.size(); ++i) {
- ExecContext *xc = execContexts[i];
-
- // initialize CPU, including PC
- TheISA::initCPU(xc, xc->readCpuId());
- }
-#endif
- frontEnd->renameTable.copyFrom(thread.renameTable);
- backEnd->renameTable.copyFrom(thread.renameTable);
-
- thread.inSyscall = false;
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::serialize(std::ostream &os)
-{
- BaseCPU::serialize(os);
- SERIALIZE_ENUM(_status);
- nameOut(os, csprintf("%s.xc", name()));
- ozoneXC.serialize(os);
- nameOut(os, csprintf("%s.tickEvent", name()));
- tickEvent.serialize(os);
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::unserialize(Checkpoint *cp, const std::string &section)
-{
- BaseCPU::unserialize(cp, section);
- UNSERIALIZE_ENUM(_status);
- ozoneXC.unserialize(cp, csprintf("%s.xc", section));
- tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
-}
-
-template <class Impl>
-Fault
-OzoneCPU<Impl>::copySrcTranslate(Addr src)
-{
- panic("Copy not implemented!\n");
- return NoFault;
-#if 0
- static bool no_warn = true;
- int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
- // Only support block sizes of 64 atm.
- assert(blk_size == 64);
- int offset = src & (blk_size - 1);
-
- // Make sure block doesn't span page
- if (no_warn &&
- (src & TheISA::PageMask) != ((src + blk_size) & TheISA::PageMask) &&
- (src >> 40) != 0xfffffc) {
- warn("Copied block source spans pages %x.", src);
- no_warn = false;
- }
-
- memReq->reset(src & ~(blk_size - 1), blk_size);
-
- // translate to physical address
- Fault fault = xc->translateDataReadReq(memReq);
-
- assert(fault != Alignment_Fault);
-
- if (fault == NoFault) {
- xc->copySrcAddr = src;
- xc->copySrcPhysAddr = memReq->paddr + offset;
- } else {
- xc->copySrcAddr = 0;
- xc->copySrcPhysAddr = 0;
- }
- return fault;
-#endif
-}
-
-template <class Impl>
-Fault
-OzoneCPU<Impl>::copy(Addr dest)
-{
- panic("Copy not implemented!\n");
- return NoFault;
-#if 0
- static bool no_warn = true;
- int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
- // Only support block sizes of 64 atm.
- assert(blk_size == 64);
- uint8_t data[blk_size];
- //assert(xc->copySrcAddr);
- int offset = dest & (blk_size - 1);
-
- // Make sure block doesn't span page
- if (no_warn &&
- (dest & TheISA::PageMask) != ((dest + blk_size) & TheISA::PageMask) &&
- (dest >> 40) != 0xfffffc) {
- no_warn = false;
- warn("Copied block destination spans pages %x. ", dest);
- }
-
- memReq->reset(dest & ~(blk_size -1), blk_size);
- // translate to physical address
- Fault fault = xc->translateDataWriteReq(memReq);
-
- assert(fault != Alignment_Fault);
-
- if (fault == NoFault) {
- Addr dest_addr = memReq->paddr + offset;
- // Need to read straight from memory since we have more than 8 bytes.
- memReq->paddr = xc->copySrcPhysAddr;
- xc->mem->read(memReq, data);
- memReq->paddr = dest_addr;
- xc->mem->write(memReq, data);
- if (dcacheInterface) {
- memReq->cmd = Copy;
- memReq->completionEvent = NULL;
- memReq->paddr = xc->copySrcPhysAddr;
- memReq->dest = dest_addr;
- memReq->size = 64;
- memReq->time = curTick;
- dcacheInterface->access(memReq);
- }
- }
- return fault;
-#endif
-}
-
-#if FULL_SYSTEM
-template <class Impl>
-Addr
-OzoneCPU<Impl>::dbg_vtophys(Addr addr)
-{
- return vtophys(xcProxy, addr);
-}
-#endif // FULL_SYSTEM
-
-#if FULL_SYSTEM
-template <class Impl>
-void
-OzoneCPU<Impl>::post_interrupt(int int_num, int index)
-{
- BaseCPU::post_interrupt(int_num, index);
-
- if (_status == Idle) {
- DPRINTF(IPI,"Suspended Processor awoke\n");
-// thread.activate();
- // Hack for now. Otherwise might have to go through the xcProxy, or
- // I need to figure out what's the right thing to call.
- activateContext(thread.tid, 1);
- }
-}
-#endif // FULL_SYSTEM
-
-/* start simulation, program loaded, processor precise state initialized */
-template <class Impl>
-void
-OzoneCPU<Impl>::tick()
-{
- DPRINTF(OzoneCPU, "\n\nOzoneCPU: Ticking cpu.\n");
-
- _status = Running;
- thread.renameTable[ZeroReg]->setIntResult(0);
- thread.renameTable[ZeroReg+TheISA::FP_Base_DepTag]->
- setDoubleResult(0.0);
-
- comm.advance();
- frontEnd->tick();
- backEnd->tick();
-
- // check for instruction-count-based events
- comInstEventQueue[0]->serviceEvents(numInst);
-
- if (!tickEvent.scheduled() && _status == Running)
- tickEvent.schedule(curTick + cycles(1));
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::squashFromXC()
-{
- thread.inSyscall = true;
- backEnd->generateXCEvent();
-}
-
-#if !FULL_SYSTEM
-template <class Impl>
-void
-OzoneCPU<Impl>::syscall()
-{
- // Not sure this copy is needed, depending on how the XC proxy is made.
- thread.renameTable.copyFrom(backEnd->renameTable);
-
- thread.inSyscall = true;
-
- thread.funcExeInst++;
-
- DPRINTF(OzoneCPU, "FuncExeInst: %i\n", thread.funcExeInst);
-
- thread.process->syscall(xcProxy);
-
- thread.funcExeInst--;
-
- thread.inSyscall = false;
-
- frontEnd->renameTable.copyFrom(thread.renameTable);
- backEnd->renameTable.copyFrom(thread.renameTable);
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
-{
- // check for error condition. Alpha syscall convention is to
- // indicate success/failure in reg a3 (r19) and put the
- // return value itself in the standard return value reg (v0).
- if (return_value.successful()) {
- // no error
- thread.renameTable[SyscallSuccessReg]->setIntResult(0);
- thread.renameTable[ReturnValueReg]->setIntResult(
- return_value.value());
- } else {
- // got an error, return details
- thread.renameTable[SyscallSuccessReg]->setIntResult((IntReg) -1);
- thread.renameTable[ReturnValueReg]->setIntResult(
- -return_value.value());
- }
-}
-#else
-template <class Impl>
-Fault
-OzoneCPU<Impl>::hwrei()
-{
- // Need to move this to ISA code
- // May also need to make this per thread
-
- lockFlag = false;
- lockAddrList.clear();
- thread.kernelStats->hwrei();
-
- checkInterrupts = true;
-
- // FIXME: XXX check for interrupts? XXX
- return NoFault;
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::processInterrupts()
-{
- // Check for interrupts here. For now can copy the code that
- // exists within isa_fullsys_traits.hh. Also assume that thread 0
- // is the one that handles the interrupts.
-
- // Check if there are any outstanding interrupts
- //Handle the interrupts
- int ipl = 0;
- int summary = 0;
-
- checkInterrupts = false;
-
- if (thread.readMiscReg(IPR_ASTRR))
- panic("asynchronous traps not implemented\n");
-
- if (thread.readMiscReg(IPR_SIRR)) {
- for (int i = INTLEVEL_SOFTWARE_MIN;
- i < INTLEVEL_SOFTWARE_MAX; i++) {
- if (thread.readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
- // See table 4-19 of the 21164 hardware reference
- ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- uint64_t interrupts = intr_status();
-
- if (interrupts) {
- for (int i = INTLEVEL_EXTERNAL_MIN;
- i < INTLEVEL_EXTERNAL_MAX; i++) {
- if (interrupts & (ULL(1) << i)) {
- // See table 4-19 of the 21164 hardware reference
- ipl = i;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- if (ipl && ipl > thread.readMiscReg(IPR_IPLR)) {
- thread.setMiscReg(IPR_ISR, summary);
- thread.setMiscReg(IPR_INTID, ipl);
- // @todo: Make this more transparent
- if (checker) {
- checker->cpuXCBase()->setMiscReg(IPR_ISR, summary);
- checker->cpuXCBase()->setMiscReg(IPR_INTID, ipl);
- }
- Fault fault = new InterruptFault;
- fault->invoke(thread.getXCProxy());
- DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
- thread.readMiscReg(IPR_IPLR), ipl, summary);
- }
-}
-
-template <class Impl>
-bool
-OzoneCPU<Impl>::simPalCheck(int palFunc)
-{
- // Need to move this to ISA code
- // May also need to make this per thread
- thread.kernelStats->callpal(palFunc, xcProxy);
-
- switch (palFunc) {
- case PAL::halt:
- haltContext(thread.tid);
- if (--System::numSystemsRunning == 0)
- new SimExitEvent("all cpus halted");
- break;
-
- case PAL::bpt:
- case PAL::bugchk:
- if (system->breakpoint())
- return false;
- break;
- }
-
- return true;
-}
-#endif
-
-template <class Impl>
-BaseCPU *
-OzoneCPU<Impl>::OzoneXC::getCpuPtr()
-{
- return cpu;
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::setCpuId(int id)
-{
- cpu->cpuId = id;
- thread->cpuId = id;
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::setStatus(Status new_status)
-{
- thread->_status = new_status;
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::activate(int delay)
-{
- cpu->activateContext(thread->tid, delay);
-}
-
-/// Set the status to Suspended.
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::suspend()
-{
- cpu->suspendContext(thread->tid);
-}
-
-/// Set the status to Unallocated.
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::deallocate()
-{
- cpu->deallocateContext(thread->tid);
-}
-
-/// Set the status to Halted.
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::halt()
-{
- cpu->haltContext(thread->tid);
-}
-
-#if FULL_SYSTEM
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::dumpFuncProfile()
-{ }
-#endif
-
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::takeOverFrom(ExecContext *old_context)
-{
- // some things should already be set up
- assert(getMemPtr() == old_context->getMemPtr());
-#if FULL_SYSTEM
- assert(getSystemPtr() == old_context->getSystemPtr());
-#else
- assert(getProcessPtr() == old_context->getProcessPtr());
-#endif
-
- // copy over functional state
- setStatus(old_context->status());
- copyArchRegs(old_context);
- setCpuId(old_context->readCpuId());
-
-#if !FULL_SYSTEM
- setFuncExeInst(old_context->readFuncExeInst());
-#else
- EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent();
- if (other_quiesce) {
- // Point the quiesce event's XC at this XC so that it wakes up
- // the proper CPU.
- other_quiesce->xc = this;
- }
- if (thread->quiesceEvent) {
- thread->quiesceEvent->xc = this;
- }
-
- thread->kernelStats = old_context->getKernelStats();
-// storeCondFailures = 0;
- cpu->lockFlag = false;
-#endif
-
- old_context->setStatus(ExecContext::Unallocated);
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::regStats(const std::string &name)
-{
-#if FULL_SYSTEM
- thread->kernelStats = new Kernel::Statistics(cpu->system);
- thread->kernelStats->regStats(name + ".kern");
-#endif
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::serialize(std::ostream &os)
-{ }
-
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::unserialize(Checkpoint *cp, const std::string &section)
-{ }
-
-#if FULL_SYSTEM
-template <class Impl>
-EndQuiesceEvent *
-OzoneCPU<Impl>::OzoneXC::getQuiesceEvent()
-{
- return thread->quiesceEvent;
-}
-
-template <class Impl>
-Tick
-OzoneCPU<Impl>::OzoneXC::readLastActivate()
-{
- return thread->lastActivate;
-}
-
-template <class Impl>
-Tick
-OzoneCPU<Impl>::OzoneXC::readLastSuspend()
-{
- return thread->lastSuspend;
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::profileClear()
-{
- if (thread->profile)
- thread->profile->clear();
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::profileSample()
-{
- if (thread->profile)
- thread->profile->sample(thread->profileNode, thread->profilePC);
-}
-#endif
-
-template <class Impl>
-int
-OzoneCPU<Impl>::OzoneXC::getThreadNum()
-{
- return thread->tid;
-}
-
-// Also somewhat obnoxious. Really only used for the TLB fault.
-template <class Impl>
-TheISA::MachInst
-OzoneCPU<Impl>::OzoneXC::getInst()
-{
- return thread->inst;
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::copyArchRegs(ExecContext *xc)
-{
- thread->PC = xc->readPC();
- thread->nextPC = xc->readNextPC();
-
- cpu->frontEnd->setPC(thread->PC);
- cpu->frontEnd->setNextPC(thread->nextPC);
-
- for (int i = 0; i < TheISA::TotalNumRegs; ++i) {
- if (i < TheISA::FP_Base_DepTag) {
- thread->renameTable[i]->setIntResult(xc->readIntReg(i));
- } else if (i < (TheISA::FP_Base_DepTag + TheISA::NumFloatRegs)) {
- int fp_idx = i - TheISA::FP_Base_DepTag;
- thread->renameTable[i]->setDoubleResult(
- xc->readFloatRegDouble(fp_idx));
- }
- }
-
-#if !FULL_SYSTEM
- thread->funcExeInst = xc->readFuncExeInst();
-#endif
-
- // Need to copy the XC values into the current rename table,
- // copy the misc regs.
- thread->regs.miscRegs.copyMiscRegs(xc);
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::clearArchRegs()
-{
- panic("Unimplemented!");
-}
-
-template <class Impl>
-uint64_t
-OzoneCPU<Impl>::OzoneXC::readIntReg(int reg_idx)
-{
- return thread->renameTable[reg_idx]->readIntResult();
-}
-
-template <class Impl>
-float
-OzoneCPU<Impl>::OzoneXC::readFloatRegSingle(int reg_idx)
-{
- int idx = reg_idx + TheISA::FP_Base_DepTag;
- return thread->renameTable[idx]->readFloatResult();
-}
-
-template <class Impl>
-double
-OzoneCPU<Impl>::OzoneXC::readFloatRegDouble(int reg_idx)
-{
- int idx = reg_idx + TheISA::FP_Base_DepTag;
- return thread->renameTable[idx]->readDoubleResult();
-}
-
-template <class Impl>
-uint64_t
-OzoneCPU<Impl>::OzoneXC::readFloatRegInt(int reg_idx)
-{
- int idx = reg_idx + TheISA::FP_Base_DepTag;
- return thread->renameTable[idx]->readIntResult();
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::setIntReg(int reg_idx, uint64_t val)
-{
- thread->renameTable[reg_idx]->setIntResult(val);
-
- if (!thread->inSyscall) {
- cpu->squashFromXC();
- }
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::setFloatRegSingle(int reg_idx, float val)
-{
- panic("Unimplemented!");
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::setFloatRegDouble(int reg_idx, double val)
-{
- int idx = reg_idx + TheISA::FP_Base_DepTag;
-
- thread->renameTable[idx]->setDoubleResult(val);
-
- if (!thread->inSyscall) {
- cpu->squashFromXC();
- }
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::setFloatRegInt(int reg_idx, uint64_t val)
-{
- panic("Unimplemented!");
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::setPC(Addr val)
-{
- thread->PC = val;
- cpu->frontEnd->setPC(val);
-
- if (!thread->inSyscall) {
- cpu->squashFromXC();
- }
-}
-
-template <class Impl>
-void
-OzoneCPU<Impl>::OzoneXC::setNextPC(Addr val)
-{
- thread->nextPC = val;
- cpu->frontEnd->setNextPC(val);
-
- if (!thread->inSyscall) {
- cpu->squashFromXC();
- }
-}
-
-template <class Impl>
-TheISA::MiscReg
-OzoneCPU<Impl>::OzoneXC::readMiscReg(int misc_reg)
-{
- return thread->regs.miscRegs.readReg(misc_reg);
-}
-
-template <class Impl>
-TheISA::MiscReg
-OzoneCPU<Impl>::OzoneXC::readMiscRegWithEffect(int misc_reg, Fault &fault)
-{
- return thread->regs.miscRegs.readRegWithEffect(misc_reg,
- fault, this);
-}
-
-template <class Impl>
-Fault
-OzoneCPU<Impl>::OzoneXC::setMiscReg(int misc_reg, const MiscReg &val)
-{
- // Needs to setup a squash event unless we're in syscall mode
- Fault ret_fault = thread->regs.miscRegs.setReg(misc_reg, val);
-
- if (!thread->inSyscall) {
- cpu->squashFromXC();
- }
-
- return ret_fault;
-}
-
-template <class Impl>
-Fault
-OzoneCPU<Impl>::OzoneXC::setMiscRegWithEffect(int misc_reg, const MiscReg &val)
-{
- // Needs to setup a squash event unless we're in syscall mode
- Fault ret_fault = thread->regs.miscRegs.setRegWithEffect(misc_reg, val,
- this);
-
- if (!thread->inSyscall) {
- cpu->squashFromXC();
- }
-
- return ret_fault;
-}
diff --git a/cpu/ozone/dyn_inst.cc b/cpu/ozone/dyn_inst.cc
deleted file mode 100644
index 3bf8b03ca..000000000
--- a/cpu/ozone/dyn_inst.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/ozone/dyn_inst_impl.hh"
-#include "cpu/ozone/ozone_impl.hh"
-#include "cpu/ozone/simple_impl.hh"
-
-template class OzoneDynInst<OzoneImpl>;
-template class OzoneDynInst<SimpleImpl>;
-
diff --git a/cpu/ozone/dyn_inst.hh b/cpu/ozone/dyn_inst.hh
deleted file mode 100644
index 5d48bb361..000000000
--- a/cpu/ozone/dyn_inst.hh
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2005-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_OZONE_DYN_INST_HH__
-#define __CPU_OZONE_DYN_INST_HH__
-
-#include "arch/isa_traits.hh"
-#include "config/full_system.hh"
-#include "cpu/base_dyn_inst.hh"
-#include "cpu/ozone/cpu.hh" // MUST include this
-#include "cpu/inst_seq.hh"
-#include "cpu/ozone/simple_impl.hh" // Would be nice to not have to include this
-#include "cpu/ozone/ozone_impl.hh"
-
-#include <list>
-#include <vector>
-
-template <class Impl>
-class OzoneDynInst : public BaseDynInst<Impl>
-{
- public:
- // Typedefs
- typedef typename Impl::FullCPU FullCPU;
-
- typedef typename FullCPU::ImplState ImplState;
-
- // Typedef for DynInstPtr. This is really just a RefCountingPtr<OoODynInst>.
- typedef typename Impl::DynInstPtr DynInstPtr;
-
- typedef TheISA::ExtMachInst ExtMachInst;
- typedef TheISA::MachInst MachInst;
- typedef TheISA::MiscReg MiscReg;
- typedef typename std::list<DynInstPtr>::iterator ListIt;
-
- // Note that this is duplicated from the BaseDynInst class; I'm
- // simply not sure the enum would carry through so I could use it
- // in array declarations in this class.
- enum {
- MaxInstSrcRegs = TheISA::MaxInstSrcRegs,
- MaxInstDestRegs = TheISA::MaxInstDestRegs
- };
-
- OzoneDynInst(FullCPU *cpu);
-
- OzoneDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC,
- InstSeqNum seq_num, FullCPU *cpu);
-
- OzoneDynInst(StaticInstPtr inst);
-
- ~OzoneDynInst();
-
- void setSrcInst(DynInstPtr &newSrcInst, int regIdx)
- { srcInsts[regIdx] = newSrcInst; }
-
- bool srcInstReady(int regIdx);
-
- void setPrevDestInst(DynInstPtr &oldDestInst, int regIdx)
- { prevDestInst[regIdx] = oldDestInst; }
-
- DynInstPtr &getPrevDestInst(int regIdx)
- { return prevDestInst[regIdx]; }
-
- void addDependent(DynInstPtr &dependent_inst);
-
- std::vector<DynInstPtr> &getDependents() { return dependents; }
- std::vector<DynInstPtr> &getMemDeps() { return memDependents; }
- std::list<DynInstPtr> &getMemSrcs() { return srcMemInsts; }
-
- void wakeDependents();
-
- void wakeMemDependents();
-
- void addMemDependent(DynInstPtr &inst) { memDependents.push_back(inst); }
-
- void addSrcMemInst(DynInstPtr &inst) { srcMemInsts.push_back(inst); }
-
- void markMemInstReady(OzoneDynInst<Impl> *inst);
-
- // For now I will remove instructions from the list when they wake
- // up. In the future, you only really need a counter.
- bool memDepReady() { return srcMemInsts.empty(); }
-
- private:
- void initInstPtrs();
-
- std::vector<DynInstPtr> dependents;
-
- std::vector<DynInstPtr> memDependents;
-
- std::list<DynInstPtr> srcMemInsts;
-
- /** The instruction that produces the value of the source
- * registers. These may be NULL if the value has already been
- * read from the source instruction.
- */
- DynInstPtr srcInsts[MaxInstSrcRegs];
-
- /**
- * Previous rename instruction for this destination.
- */
- DynInstPtr prevDestInst[MaxInstSrcRegs];
-
- public:
-
- Fault initiateAcc();
-
- Fault completeAcc();
-
- // The register accessor methods provide the index of the
- // instruction's operand (e.g., 0 or 1), not the architectural
- // register index, to simplify the implementation of register
- // renaming. We find the architectural register index by indexing
- // into the instruction's own operand index table. Note that a
- // raw pointer to the StaticInst is provided instead of a
- // ref-counted StaticInstPtr to redice overhead. This is fine as
- // long as these methods don't copy the pointer into any long-term
- // storage (which is pretty hard to imagine they would have reason
- // to do).
-
- uint64_t readIntReg(const StaticInst *si, int idx)
- {
- return srcInsts[idx]->readIntResult();
- }
-
- float readFloatRegSingle(const StaticInst *si, int idx)
- {
- return srcInsts[idx]->readFloatResult();
- }
-
- double readFloatRegDouble(const StaticInst *si, int idx)
- {
- return srcInsts[idx]->readDoubleResult();
- }
-
- uint64_t readFloatRegInt(const StaticInst *si, int idx)
- {
- return srcInsts[idx]->readIntResult();
- }
-
- /** @todo: Make results into arrays so they can handle multiple dest
- * registers.
- */
- void setIntReg(const StaticInst *si, int idx, uint64_t val)
- {
- BaseDynInst<Impl>::setIntReg(si, idx, val);
- }
-
- void setFloatRegSingle(const StaticInst *si, int idx, float val)
- {
- BaseDynInst<Impl>::setFloatRegSingle(si, idx, val);
- }
-
- void setFloatRegDouble(const StaticInst *si, int idx, double val)
- {
- BaseDynInst<Impl>::setFloatRegDouble(si, idx, val);
- }
-
- void setFloatRegInt(const StaticInst *si, int idx, uint64_t val)
- {
- BaseDynInst<Impl>::setFloatRegInt(si, idx, val);
- }
-
- void setIntResult(uint64_t result) { this->instResult.integer = result; }
- void setDoubleResult(double result) { this->instResult.dbl = result; }
-
- bool srcsReady();
- bool eaSrcsReady();
-
- Fault execute();
-
- Fault executeEAComp()
- { return NoFault; }
-
- Fault executeMemAcc()
- { return this->staticInst->memAccInst()->execute(this, this->traceData); }
-
- void clearDependents();
-
- void clearMemDependents();
-
- public:
- // ISA stuff
- MiscReg readMiscReg(int misc_reg);
-
- MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault);
-
- Fault setMiscReg(int misc_reg, const MiscReg &val);
-
- Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val);
-
-#if FULL_SYSTEM
- Fault hwrei();
- int readIntrFlag();
- void setIntrFlag(int val);
- bool inPalMode();
- void trap(Fault fault);
- bool simPalCheck(int palFunc);
-#else
- void syscall();
-#endif
-
- ListIt iqIt;
- bool iqItValid;
-};
-
-#endif // __CPU_OZONE_DYN_INST_HH__
diff --git a/cpu/ozone/dyn_inst_impl.hh b/cpu/ozone/dyn_inst_impl.hh
deleted file mode 100644
index f891ec515..000000000
--- a/cpu/ozone/dyn_inst_impl.hh
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (c) 2005-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "arch/faults.hh"
-#include "arch/isa_traits.hh"
-#include "config/full_system.hh"
-#include "cpu/ozone/dyn_inst.hh"
-#include "kern/kernel_stats.hh"
-
-using namespace TheISA;
-
-template <class Impl>
-OzoneDynInst<Impl>::OzoneDynInst(FullCPU *cpu)
- : BaseDynInst<Impl>(0, 0, 0, 0, cpu)
-{
- this->setResultReady();
-
- initInstPtrs();
-}
-
-template <class Impl>
-OzoneDynInst<Impl>::OzoneDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC,
- InstSeqNum seq_num, FullCPU *cpu)
- : BaseDynInst<Impl>(inst, PC, Pred_PC, seq_num, cpu)
-{
- initInstPtrs();
-}
-
-template <class Impl>
-OzoneDynInst<Impl>::OzoneDynInst(StaticInstPtr _staticInst)
- : BaseDynInst<Impl>(_staticInst)
-{
- initInstPtrs();
-}
-
-template <class Impl>
-OzoneDynInst<Impl>::~OzoneDynInst()
-{
- DPRINTF(BE, "[sn:%lli] destructor called\n", this->seqNum);
- for (int i = 0; i < this->numSrcRegs(); ++i) {
- srcInsts[i] = NULL;
- }
-
- for (int i = 0; i < this->numDestRegs(); ++i) {
- prevDestInst[i] = NULL;
- }
-
- dependents.clear();
-}
-
-template <class Impl>
-Fault
-OzoneDynInst<Impl>::execute()
-{
- // @todo: Pretty convoluted way to avoid squashing from happening when using
- // the XC during an instruction's execution (specifically for instructions
- // that have sideeffects that use the XC). Fix this.
- bool in_syscall = this->thread->inSyscall;
- this->thread->inSyscall = true;
-
- this->fault = this->staticInst->execute(this, this->traceData);
-
- this->thread->inSyscall = in_syscall;
-
- return this->fault;
-}
-
-template <class Impl>
-Fault
-OzoneDynInst<Impl>::initiateAcc()
-{
- // @todo: Pretty convoluted way to avoid squashing from happening when using
- // the XC during an instruction's execution (specifically for instructions
- // that have sideeffects that use the XC). Fix this.
- bool in_syscall = this->thread->inSyscall;
- this->thread->inSyscall = true;
-
- this->fault = this->staticInst->initiateAcc(this, this->traceData);
-
- this->thread->inSyscall = in_syscall;
-
- return this->fault;
-}
-
-template <class Impl>
-Fault
-OzoneDynInst<Impl>::completeAcc()
-{
- if (this->isLoad()) {
- this->fault = this->staticInst->completeAcc(this->req->data,
- this,
- this->traceData);
- } else if (this->isStore()) {
- this->fault = this->staticInst->completeAcc((uint8_t*)&this->req->result,
- this,
- this->traceData);
- } else {
- panic("Unknown type!");
- }
-
- return this->fault;
-}
-
-template <class Impl>
-bool
-OzoneDynInst<Impl>::srcInstReady(int regIdx)
-{
- return srcInsts[regIdx]->isResultReady();
-}
-
-template <class Impl>
-void
-OzoneDynInst<Impl>::addDependent(DynInstPtr &dependent_inst)
-{
- dependents.push_back(dependent_inst);
-}
-
-template <class Impl>
-void
-OzoneDynInst<Impl>::wakeDependents()
-{
- for (int i = 0; i < dependents.size(); ++i) {
- dependents[i]->markSrcRegReady();
- }
-}
-
-template <class Impl>
-void
-OzoneDynInst<Impl>::wakeMemDependents()
-{
- for (int i = 0; i < memDependents.size(); ++i) {
- memDependents[i]->markMemInstReady(this);
- }
-}
-
-template <class Impl>
-void
-OzoneDynInst<Impl>::markMemInstReady(OzoneDynInst<Impl> *inst)
-{
- ListIt mem_it = srcMemInsts.begin();
- while ((*mem_it) != inst && mem_it != srcMemInsts.end()) {
- mem_it++;
- }
- assert(mem_it != srcMemInsts.end());
-
- srcMemInsts.erase(mem_it);
-}
-
-template <class Impl>
-void
-OzoneDynInst<Impl>::initInstPtrs()
-{
- for (int i = 0; i < MaxInstSrcRegs; ++i) {
- srcInsts[i] = NULL;
- }
- iqItValid = false;
-}
-
-template <class Impl>
-bool
-OzoneDynInst<Impl>::srcsReady()
-{
- for (int i = 0; i < this->numSrcRegs(); ++i) {
- if (!srcInsts[i]->isResultReady())
- return false;
- }
-
- return true;
-}
-
-template <class Impl>
-bool
-OzoneDynInst<Impl>::eaSrcsReady()
-{
- for (int i = 1; i < this->numSrcRegs(); ++i) {
- if (!srcInsts[i]->isResultReady())
- return false;
- }
-
- return true;
-}
-
-template <class Impl>
-void
-OzoneDynInst<Impl>::clearDependents()
-{
- dependents.clear();
- for (int i = 0; i < this->numSrcRegs(); ++i) {
- srcInsts[i] = NULL;
- }
- for (int i = 0; i < this->numDestRegs(); ++i) {
- prevDestInst[i] = NULL;
- }
-}
-
-template <class Impl>
-void
-OzoneDynInst<Impl>::clearMemDependents()
-{
- memDependents.clear();
-}
-
-template <class Impl>
-MiscReg
-OzoneDynInst<Impl>::readMiscReg(int misc_reg)
-{
- return this->thread->readMiscReg(misc_reg);
-}
-
-template <class Impl>
-MiscReg
-OzoneDynInst<Impl>::readMiscRegWithEffect(int misc_reg, Fault &fault)
-{
- return this->thread->readMiscRegWithEffect(misc_reg, fault);
-}
-
-template <class Impl>
-Fault
-OzoneDynInst<Impl>::setMiscReg(int misc_reg, const MiscReg &val)
-{
- this->setIntResult(val);
- return this->thread->setMiscReg(misc_reg, val);
-}
-
-template <class Impl>
-Fault
-OzoneDynInst<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val)
-{
- return this->thread->setMiscRegWithEffect(misc_reg, val);
-}
-
-#if FULL_SYSTEM
-
-template <class Impl>
-Fault
-OzoneDynInst<Impl>::hwrei()
-{
- if (!this->cpu->inPalMode(this->readPC()))
- return new AlphaISA::UnimplementedOpcodeFault;
-
- this->setNextPC(this->thread->readMiscReg(AlphaISA::IPR_EXC_ADDR));
-
- this->cpu->hwrei();
-
- // FIXME: XXX check for interrupts? XXX
- return NoFault;
-}
-
-template <class Impl>
-int
-OzoneDynInst<Impl>::readIntrFlag()
-{
-return this->cpu->readIntrFlag();
-}
-
-template <class Impl>
-void
-OzoneDynInst<Impl>::setIntrFlag(int val)
-{
- this->cpu->setIntrFlag(val);
-}
-
-template <class Impl>
-bool
-OzoneDynInst<Impl>::inPalMode()
-{
- return this->cpu->inPalMode();
-}
-
-template <class Impl>
-void
-OzoneDynInst<Impl>::trap(Fault fault)
-{
- fault->invoke(this->thread->getXCProxy());
-}
-
-template <class Impl>
-bool
-OzoneDynInst<Impl>::simPalCheck(int palFunc)
-{
- return this->cpu->simPalCheck(palFunc);
-}
-#else
-template <class Impl>
-void
-OzoneDynInst<Impl>::syscall()
-{
- this->cpu->syscall();
-}
-#endif
diff --git a/cpu/ozone/ea_list.cc b/cpu/ozone/ea_list.cc
deleted file mode 100644
index 6114a0ca1..000000000
--- a/cpu/ozone/ea_list.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "arch/isa_traits.hh"
-#include "cpu/inst_seq.hh"
-#include "cpu/ooo_cpu/ea_list.hh"
-
-void
-EAList::addAddr(const InstSeqNum &new_sn, const Addr &new_ea)
-{
- instEA newEA(new_sn, new_ea);
-
- eaList.push_back(newEA);
-}
-
-void
-EAList::clearAddr(const InstSeqNum &sn_to_clear, const Addr &ea_to_clear)
-{
- eaListIt list_it = eaList.begin();
-
- while (list_it != eaList.end() && (*list_it).first != sn_to_clear) {
- assert((*list_it).second == ea_to_clear);
- }
-}
-
-bool
-EAList::checkConflict(const InstSeqNum &check_sn, const Addr &check_ea) const
-{
- const constEAListIt list_it = eaList.begin();
-
- while (list_it != eaList.end() && (*list_it).first < check_sn) {
- if ((*list_it).second == check_ea) {
- return true;
- }
- }
-
- return false;
-}
-
-void
-EAList::clear()
-{
- eaList.clear();
-}
-
-void
-EAList::commit(const InstSeqNum &commit_sn)
-{
- while (!eaList.empty() && eaList.front().first <= commit_sn) {
- eaList.pop_front();
- }
-}
diff --git a/cpu/ozone/ea_list.hh b/cpu/ozone/ea_list.hh
deleted file mode 100644
index c0eee4bb8..000000000
--- a/cpu/ozone/ea_list.hh
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_EA_LIST_HH__
-#define __CPU_EA_LIST_HH__
-
-#include <list>
-#include <utility>
-
-#include "arch/isa_traits.hh"
-#include "cpu/inst_seq.hh"
-
-/**
- * Simple class to hold onto a list of pairs, each pair having a memory
- * instruction's sequence number and effective addr. This list can be used
- * for memory disambiguation. However, if I ever want to forward results, I
- * may have to use a list that holds DynInstPtrs. Hence this may change in
- * the future.
- */
-class EAList {
- private:
- typedef std::pair<InstSeqNum, Addr> instEA;
- typedef std::list<instEA>::iterator eaListIt;
- typedef std::list<instEA>::const_iterator constEAListIt;
-
- std::list<instEA> eaList;
-
- public:
- EAList() { }
- ~EAList() { }
-
- void addAddr(const InstSeqNum &new_sn, const Addr &new_ea);
-
- void clearAddr(const InstSeqNum &sn_to_clear, const Addr &ea_to_clear);
-
- /** Checks if any instructions older than check_sn have a conflicting
- * address with check_ea. Note that this function does not handle the
- * sequence number rolling over.
- */
- bool checkConflict(const InstSeqNum &check_sn, const Addr &check_ea) const;
-
- void clear();
-
- void commit(const InstSeqNum &commit_sn);
-};
-
-#endif // __CPU_EA_LIST_HH__
diff --git a/cpu/ozone/front_end.cc b/cpu/ozone/front_end.cc
deleted file mode 100644
index a974d43cb..000000000
--- a/cpu/ozone/front_end.cc
+++ /dev/null
@@ -1,7 +0,0 @@
-
-#include "cpu/ozone/front_end_impl.hh"
-#include "cpu/ozone/ozone_impl.hh"
-#include "cpu/ozone/simple_impl.hh"
-
-template class FrontEnd<OzoneImpl>;
-template class FrontEnd<SimpleImpl>;
diff --git a/cpu/ozone/front_end.hh b/cpu/ozone/front_end.hh
deleted file mode 100644
index dd382491f..000000000
--- a/cpu/ozone/front_end.hh
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_OZONE_FRONT_END_HH__
-#define __CPU_OZONE_FRONT_END_HH__
-
-#include <deque>
-
-#include "cpu/inst_seq.hh"
-#include "cpu/o3/bpred_unit.hh"
-#include "cpu/ozone/rename_table.hh"
-#include "mem/mem_req.hh"
-#include "sim/eventq.hh"
-#include "sim/stats.hh"
-
-class ExecContext;
-class MemInterface;
-template <class>
-class OzoneThreadState;
-class PageTable;
-template <class>
-class TimeBuffer;
-
-template <class Impl>
-class FrontEnd
-{
- public:
- typedef typename Impl::Params Params;
- typedef typename Impl::DynInst DynInst;
- typedef typename Impl::DynInstPtr DynInstPtr;
- typedef typename Impl::FullCPU FullCPU;
- typedef typename Impl::BackEnd BackEnd;
-
- typedef typename Impl::FullCPU::OzoneXC OzoneXC;
- typedef typename Impl::FullCPU::CommStruct CommStruct;
-
- FrontEnd(Params *params);
-
- std::string name() const;
-
- void setCPU(FullCPU *cpu_ptr)
- { cpu = cpu_ptr; }
-
- void setBackEnd(BackEnd *back_end_ptr)
- { backEnd = back_end_ptr; }
-
- void setCommBuffer(TimeBuffer<CommStruct> *_comm);
-
- void setXC(ExecContext *xc_ptr);
-
- void setThreadState(OzoneThreadState<Impl> *thread_ptr)
- { thread = thread_ptr; }
-
- void regStats();
-
- void tick();
- Fault fetchCacheLine();
- void processInst(DynInstPtr &inst);
- void squash(const InstSeqNum &squash_num, const Addr &next_PC,
- const bool is_branch = false, const bool branch_taken = false);
- DynInstPtr getInst();
-
- void processCacheCompletion(MemReqPtr &req);
-
- void addFreeRegs(int num_freed);
-
- bool isEmpty() { return instBuffer.empty(); }
-
- void switchOut();
-
- void doSwitchOut();
-
- void takeOverFrom(ExecContext *old_xc = NULL);
-
- bool isSwitchedOut() { return switchedOut; }
-
- bool switchedOut;
-
- private:
- bool updateStatus();
-
- void checkBE();
- DynInstPtr getInstFromCacheline();
- void renameInst(DynInstPtr &inst);
- // Returns true if we need to stop the front end this cycle
- bool processBarriers(DynInstPtr &inst);
-
- void handleFault(Fault &fault);
- public:
- Fault getFault() { return fetchFault; }
- private:
- Fault fetchFault;
-
- // Align an address (typically a PC) to the start of an I-cache block.
- // We fold in the PISA 64- to 32-bit conversion here as well.
- Addr icacheBlockAlignPC(Addr addr)
- {
- addr = TheISA::realPCToFetchPC(addr);
- return (addr & ~(cacheBlkMask));
- }
-
- InstSeqNum getAndIncrementInstSeq()
- { return cpu->globalSeqNum++; }
-
- public:
- FullCPU *cpu;
-
- BackEnd *backEnd;
-
- ExecContext *xc;
-
- OzoneThreadState<Impl> *thread;
-
- enum Status {
- Running,
- Idle,
- IcacheMissStall,
- IcacheMissComplete,
- SerializeBlocked,
- SerializeComplete,
- RenameBlocked,
- QuiescePending,
- TrapPending,
- BEBlocked
- };
-
- Status status;
-
- private:
- TimeBuffer<CommStruct> *comm;
- typename TimeBuffer<CommStruct>::wire fromCommit;
-
- typedef typename Impl::BranchPred BranchPred;
-
- BranchPred branchPred;
-
- class ICacheCompletionEvent : public Event
- {
- private:
- MemReqPtr req;
- FrontEnd *frontEnd;
-
- public:
- ICacheCompletionEvent(MemReqPtr &_req, FrontEnd *_fe);
-
- virtual void process();
- virtual const char *description();
- };
-
- MemInterface *icacheInterface;
-
-#if !FULL_SYSTEM
- PageTable *pTable;
-#endif
-
- MemReqPtr memReq;
-
- /** Mask to get a cache block's address. */
- Addr cacheBlkMask;
-
- unsigned cacheBlkSize;
-
- Addr cacheBlkPC;
-
- /** The cache line being fetched. */
- uint8_t *cacheData;
-
- bool fetchCacheLineNextCycle;
-
- bool cacheBlkValid;
-
- public:
- RenameTable<Impl> renameTable;
-
- private:
- Addr PC;
- Addr nextPC;
-
- public:
- void setPC(Addr val) { PC = val; }
- void setNextPC(Addr val) { nextPC = val; }
-
- void wakeFromQuiesce();
-
- void dumpInsts();
-
- private:
- typedef typename std::deque<DynInstPtr> InstBuff;
- typedef typename InstBuff::iterator InstBuffIt;
-
- InstBuff instBuffer;
-
- int instBufferSize;
-
- int maxInstBufferSize;
-
- int width;
-
- int freeRegs;
-
- int numPhysRegs;
-
- bool serializeNext;
-
- DynInstPtr barrierInst;
-
- public:
- bool interruptPending;
- private:
- // number of idle cycles
-/*
- Stats::Average<> notIdleFraction;
- Stats::Formula idleFraction;
-*/
- // @todo: Consider making these vectors and tracking on a per thread basis.
- /** Stat for total number of cycles stalled due to an icache miss. */
- Stats::Scalar<> icacheStallCycles;
- /** Stat for total number of fetched instructions. */
- Stats::Scalar<> fetchedInsts;
- Stats::Scalar<> fetchedBranches;
- /** Stat for total number of predicted branches. */
- Stats::Scalar<> predictedBranches;
- /** Stat for total number of cycles spent fetching. */
- Stats::Scalar<> fetchCycles;
-
- Stats::Scalar<> fetchIdleCycles;
- /** Stat for total number of cycles spent squashing. */
- Stats::Scalar<> fetchSquashCycles;
- /** Stat for total number of cycles spent blocked due to other stages in
- * the pipeline.
- */
- Stats::Scalar<> fetchBlockedCycles;
- /** Stat for total number of fetched cache lines. */
- Stats::Scalar<> fetchedCacheLines;
-
- Stats::Scalar<> fetchIcacheSquashes;
- /** Distribution of number of instructions fetched each cycle. */
- Stats::Distribution<> fetchNisnDist;
-// Stats::Vector<> qfull_iq_occupancy;
-// Stats::VectorDistribution<> qfull_iq_occ_dist_;
- Stats::Formula idleRate;
- Stats::Formula branchRate;
- Stats::Formula fetchRate;
- Stats::Scalar<> IFQCount; // cumulative IFQ occupancy
- Stats::Formula IFQOccupancy;
- Stats::Formula IFQLatency;
- Stats::Scalar<> IFQFcount; // cumulative IFQ full count
- Stats::Formula IFQFullRate;
-
- Stats::Scalar<> dispatchCountStat;
- Stats::Scalar<> dispatchedSerializing;
- Stats::Scalar<> dispatchedTempSerializing;
- Stats::Scalar<> dispatchSerializeStallCycles;
- Stats::Formula dispatchRate;
- Stats::Formula regIntFull;
- Stats::Formula regFpFull;
-};
-
-#endif // __CPU_OZONE_FRONT_END_HH__
diff --git a/cpu/ozone/front_end_impl.hh b/cpu/ozone/front_end_impl.hh
deleted file mode 100644
index ffbcf3340..000000000
--- a/cpu/ozone/front_end_impl.hh
+++ /dev/null
@@ -1,920 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "arch/faults.hh"
-#include "arch/isa_traits.hh"
-#include "base/statistics.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/exetrace.hh"
-#include "cpu/ozone/front_end.hh"
-#include "mem/mem_interface.hh"
-#include "sim/byte_swap.hh"
-
-using namespace TheISA;
-
-template <class Impl>
-FrontEnd<Impl>::FrontEnd(Params *params)
- : branchPred(params),
- icacheInterface(params->icacheInterface),
- instBufferSize(0),
- maxInstBufferSize(params->maxInstBufferSize),
- width(params->frontEndWidth),
- freeRegs(params->numPhysicalRegs),
- numPhysRegs(params->numPhysicalRegs),
- serializeNext(false),
- interruptPending(false)
-{
- switchedOut = false;
-
- status = Idle;
-
- memReq = NULL;
- // Size of cache block.
- cacheBlkSize = icacheInterface ? icacheInterface->getBlockSize() : 64;
-
- assert(isPowerOf2(cacheBlkSize));
-
- // Create mask to get rid of offset bits.
- cacheBlkMask = (cacheBlkSize - 1);
-
- // Create space to store a cache line.
- cacheData = new uint8_t[cacheBlkSize];
-
- fetchCacheLineNextCycle = true;
-
- cacheBlkValid = false;
-
-#if !FULL_SYSTEM
-// pTable = params->pTable;
-#endif
- fetchFault = NoFault;
-}
-
-template <class Impl>
-std::string
-FrontEnd<Impl>::name() const
-{
- return cpu->name() + ".frontend";
-}
-
-template <class Impl>
-void
-FrontEnd<Impl>::setCommBuffer(TimeBuffer<CommStruct> *_comm)
-{
- comm = _comm;
- // @todo: Hardcoded for now. Allow this to be set by a latency.
- fromCommit = comm->getWire(-1);
-}
-
-template <class Impl>
-void
-FrontEnd<Impl>::setXC(ExecContext *xc_ptr)
-{
- xc = xc_ptr;
-}
-
-template <class Impl>
-void
-FrontEnd<Impl>::regStats()
-{
- icacheStallCycles
- .name(name() + ".icacheStallCycles")
- .desc("Number of cycles fetch is stalled on an Icache miss")
- .prereq(icacheStallCycles);
-
- fetchedInsts
- .name(name() + ".fetchedInsts")
- .desc("Number of instructions fetch has processed")
- .prereq(fetchedInsts);
-
- fetchedBranches
- .name(name() + ".fetchedBranches")
- .desc("Number of fetched branches")
- .prereq(fetchedBranches);
-
- predictedBranches
- .name(name() + ".predictedBranches")
- .desc("Number of branches that fetch has predicted taken")
- .prereq(predictedBranches);
-
- fetchCycles
- .name(name() + ".fetchCycles")
- .desc("Number of cycles fetch has run and was not squashing or"
- " blocked")
- .prereq(fetchCycles);
-
- fetchIdleCycles
- .name(name() + ".fetchIdleCycles")
- .desc("Number of cycles fetch was idle")
- .prereq(fetchIdleCycles);
-
- fetchSquashCycles
- .name(name() + ".fetchSquashCycles")
- .desc("Number of cycles fetch has spent squashing")
- .prereq(fetchSquashCycles);
-
- fetchBlockedCycles
- .name(name() + ".fetchBlockedCycles")
- .desc("Number of cycles fetch has spent blocked")
- .prereq(fetchBlockedCycles);
-
- fetchedCacheLines
- .name(name() + ".fetchedCacheLines")
- .desc("Number of cache lines fetched")
- .prereq(fetchedCacheLines);
-
- fetchIcacheSquashes
- .name(name() + ".fetchIcacheSquashes")
- .desc("Number of outstanding Icache misses that were squashed")
- .prereq(fetchIcacheSquashes);
-
- fetchNisnDist
- .init(/* base value */ 0,
- /* last value */ width,
- /* bucket size */ 1)
- .name(name() + ".rateDist")
- .desc("Number of instructions fetched each cycle (Total)")
- .flags(Stats::pdf);
-
- idleRate
- .name(name() + ".idleRate")
- .desc("Percent of cycles fetch was idle")
- .prereq(idleRate);
- idleRate = fetchIdleCycles * 100 / cpu->numCycles;
-
- branchRate
- .name(name() + ".branchRate")
- .desc("Number of branch fetches per cycle")
- .flags(Stats::total);
- branchRate = fetchedBranches / cpu->numCycles;
-
- fetchRate
- .name(name() + ".rate")
- .desc("Number of inst fetches per cycle")
- .flags(Stats::total);
- fetchRate = fetchedInsts / cpu->numCycles;
-
- IFQCount
- .name(name() + ".IFQ:count")
- .desc("cumulative IFQ occupancy")
- ;
-
- IFQFcount
- .name(name() + ".IFQ:fullCount")
- .desc("cumulative IFQ full count")
- .flags(Stats::total)
- ;
-
- IFQOccupancy
- .name(name() + ".IFQ:occupancy")
- .desc("avg IFQ occupancy (inst's)")
- ;
- IFQOccupancy = IFQCount / cpu->numCycles;
-
- IFQLatency
- .name(name() + ".IFQ:latency")
- .desc("avg IFQ occupant latency (cycle's)")
- .flags(Stats::total)
- ;
-
- IFQFullRate
- .name(name() + ".IFQ:fullRate")
- .desc("fraction of time (cycles) IFQ was full")
- .flags(Stats::total);
- ;
- IFQFullRate = IFQFcount * Stats::constant(100) / cpu->numCycles;
-
- dispatchCountStat
- .name(name() + ".DIS:count")
- .desc("cumulative count of dispatched insts")
- .flags(Stats::total)
- ;
-
- dispatchedSerializing
- .name(name() + ".DIS:serializingInsts")
- .desc("count of serializing insts dispatched")
- .flags(Stats::total)
- ;
-
- dispatchedTempSerializing
- .name(name() + ".DIS:tempSerializingInsts")
- .desc("count of temporary serializing insts dispatched")
- .flags(Stats::total)
- ;
-
- dispatchSerializeStallCycles
- .name(name() + ".DIS:serializeStallCycles")
- .desc("count of cycles dispatch stalled for serializing inst")
- .flags(Stats::total)
- ;
-
- dispatchRate
- .name(name() + ".DIS:rate")
- .desc("dispatched insts per cycle")
- .flags(Stats::total)
- ;
- dispatchRate = dispatchCountStat / cpu->numCycles;
-
- regIntFull
- .name(name() + ".REG:int:full")
- .desc("number of cycles where there were no INT registers")
- ;
-
- regFpFull
- .name(name() + ".REG:fp:full")
- .desc("number of cycles where there were no FP registers")
- ;
- IFQLatency = IFQOccupancy / dispatchRate;
-
- branchPred.regStats();
-}
-
-template <class Impl>
-void
-FrontEnd<Impl>::tick()
-{
- if (switchedOut)
- return;
-
- // @todo: Maybe I want to just have direct communication...
- if (fromCommit->doneSeqNum) {
- branchPred.update(fromCommit->doneSeqNum, 0);
- }
-
- IFQCount += instBufferSize;
- IFQFcount += instBufferSize == maxInstBufferSize;
-
- // Fetch cache line
- if (status == IcacheMissComplete) {
- cacheBlkValid = true;
-
- status = Running;
- if (barrierInst)
- status = SerializeBlocked;
- if (freeRegs <= 0)
- status = RenameBlocked;
- checkBE();
- } else if (status == IcacheMissStall) {
- DPRINTF(FE, "Still in Icache miss stall.\n");
- icacheStallCycles++;
- return;
- }
-
- if (status == RenameBlocked || status == SerializeBlocked ||
- status == TrapPending || status == BEBlocked) {
- // Will cause a one cycle bubble between changing state and
- // restarting.
- DPRINTF(FE, "In blocked status.\n");
-
- fetchBlockedCycles++;
-
- if (status == SerializeBlocked) {
- dispatchSerializeStallCycles++;
- }
- updateStatus();
- return;
- } else if (status == QuiescePending) {
- DPRINTF(FE, "Waiting for quiesce to execute or get squashed.\n");
- return;
- } else if (status != IcacheMissComplete) {
- if (fetchCacheLineNextCycle) {
- Fault fault = fetchCacheLine();
- if (fault != NoFault) {
- handleFault(fault);
- fetchFault = fault;
- return;
- }
- fetchCacheLineNextCycle = false;
- }
- // If miss, stall until it returns.
- if (status == IcacheMissStall) {
- // Tell CPU to not tick me for now.
- return;
- }
- }
-
- fetchCycles++;
-
- int num_inst = 0;
-
- // Otherwise loop and process instructions.
- // One way to hack infinite width is to set width and maxInstBufferSize
- // both really high. Inelegant, but probably will work.
- while (num_inst < width &&
- instBufferSize < maxInstBufferSize) {
- // Get instruction from cache line.
- DynInstPtr inst = getInstFromCacheline();
-
- if (!inst) {
- // PC is no longer in the cache line, end fetch.
- // Might want to check this at the end of the cycle so that
- // there's no cycle lost to checking for a new cache line.
- DPRINTF(FE, "Need to get new cache line\n");
- fetchCacheLineNextCycle = true;
- break;
- }
-
- processInst(inst);
-
- if (status == SerializeBlocked) {
- break;
- }
-
- // Possibly push into a time buffer that estimates the front end
- // latency
- instBuffer.push_back(inst);
- ++instBufferSize;
- ++num_inst;
-
-#if FULL_SYSTEM
- if (inst->isQuiesce()) {
- warn("%lli: Quiesce instruction encountered, halting fetch!", curTick);
- status = QuiescePending;
- break;
- }
-#endif
-
- if (inst->predTaken()) {
- // Start over with tick?
- break;
- } else if (freeRegs <= 0) {
- DPRINTF(FE, "Ran out of free registers to rename to!\n");
- status = RenameBlocked;
- break;
- } else if (serializeNext) {
- break;
- }
- }
-
- fetchNisnDist.sample(num_inst);
- checkBE();
-
- DPRINTF(FE, "Num insts processed: %i, Inst Buffer size: %i, Free "
- "Regs %i\n", num_inst, instBufferSize, freeRegs);
-}
-
-template <class Impl>
-Fault
-FrontEnd<Impl>::fetchCacheLine()
-{
- // Read a cache line, based on the current PC.
-#if FULL_SYSTEM
- // Flag to say whether or not address is physical addr.
- unsigned flags = cpu->inPalMode(PC) ? PHYSICAL : 0;
-#else
- unsigned flags = 0;
-#endif // FULL_SYSTEM
- Fault fault = NoFault;
-
- if (interruptPending && flags == 0) {
- return fault;
- }
-
- // Align the fetch PC so it's at the start of a cache block.
- Addr fetch_PC = icacheBlockAlignPC(PC);
-
- DPRINTF(FE, "Fetching cache line starting at %#x.\n", fetch_PC);
-
- // Setup the memReq to do a read of the first isntruction's address.
- // Set the appropriate read size and flags as well.
- memReq = new MemReq();
-
- memReq->asid = 0;
- memReq->thread_num = 0;
- memReq->data = new uint8_t[64];
- memReq->xc = xc;
- memReq->cmd = Read;
- memReq->reset(fetch_PC, cacheBlkSize, flags);
-
- // Translate the instruction request.
- fault = cpu->translateInstReq(memReq);
-
- // Now do the timing access to see whether or not the instruction
- // exists within the cache.
- if (icacheInterface && fault == NoFault) {
-#if FULL_SYSTEM
- if (cpu->system->memctrl->badaddr(memReq->paddr) ||
- memReq->flags & UNCACHEABLE) {
- DPRINTF(FE, "Fetch: Bad address %#x (hopefully on a "
- "misspeculating path!",
- memReq->paddr);
- return TheISA::genMachineCheckFault();
- }
-#endif
-
- memReq->completionEvent = NULL;
-
- memReq->time = curTick;
- fault = cpu->mem->read(memReq, cacheData);
-
- MemAccessResult res = icacheInterface->access(memReq);
-
- // If the cache missed then schedule an event to wake
- // up this stage once the cache miss completes.
- if (icacheInterface->doEvents() && res != MA_HIT) {
- memReq->completionEvent = new ICacheCompletionEvent(memReq, this);
-
- status = IcacheMissStall;
-
- cacheBlkValid = false;
-
- DPRINTF(FE, "Cache miss.\n");
- } else {
- DPRINTF(FE, "Cache hit.\n");
-
- cacheBlkValid = true;
-
-// memcpy(cacheData, memReq->data, memReq->size);
- }
- }
-
- // Note that this will set the cache block PC a bit earlier than it should
- // be set.
- cacheBlkPC = fetch_PC;
-
- ++fetchedCacheLines;
-
- DPRINTF(FE, "Done fetching cache line.\n");
-
- return fault;
-}
-
-template <class Impl>
-void
-FrontEnd<Impl>::processInst(DynInstPtr &inst)
-{
- if (processBarriers(inst)) {
- return;
- }
-
- Addr inst_PC = inst->readPC();
-
- if (!inst->isControl()) {
- inst->setPredTarg(inst->readNextPC());
- } else {
- fetchedBranches++;
- if (branchPred.predict(inst, inst_PC, inst->threadNumber)) {
- predictedBranches++;
- }
- }
-
- Addr next_PC = inst->readPredTarg();
-
- DPRINTF(FE, "[sn:%lli] Predicted and processed inst PC %#x, next PC "
- "%#x\n", inst->seqNum, inst_PC, next_PC);
-
-// inst->setNextPC(next_PC);
-
- // Not sure where I should set this
- PC = next_PC;
-
- renameInst(inst);
-}
-
-template <class Impl>
-bool
-FrontEnd<Impl>::processBarriers(DynInstPtr &inst)
-{
- if (serializeNext) {
- inst->setSerializeBefore();
- serializeNext = false;
- } else if (!inst->isSerializing() &&
- !inst->isIprAccess() &&
- !inst->isStoreConditional()) {
- return false;
- }
-
- if ((inst->isIprAccess() || inst->isSerializeBefore()) &&
- !inst->isSerializeHandled()) {
- DPRINTF(FE, "Serialize before instruction encountered.\n");
-
- if (!inst->isTempSerializeBefore()) {
- dispatchedSerializing++;
- inst->setSerializeHandled();
- } else {
- dispatchedTempSerializing++;
- }
-
- // Change status over to SerializeBlocked so that other stages know
- // what this is blocked on.
- status = SerializeBlocked;
-
- barrierInst = inst;
- return true;
- } else if ((inst->isStoreConditional() || inst->isSerializeAfter())
- && !inst->isSerializeHandled()) {
- DPRINTF(FE, "Serialize after instruction encountered.\n");
-
- inst->setSerializeHandled();
-
- dispatchedSerializing++;
-
- serializeNext = true;
- return false;
- }
- return false;
-}
-
-template <class Impl>
-void
-FrontEnd<Impl>::handleFault(Fault &fault)
-{
- DPRINTF(FE, "Fault at fetch, telling commit\n");
-
- // We're blocked on the back end until it handles this fault.
- status = TrapPending;
-
- // Get a sequence number.
- InstSeqNum inst_seq = getAndIncrementInstSeq();
- // We will use a nop in order to carry the fault.
- ExtMachInst ext_inst = TheISA::NoopMachInst;
-
- // Create a new DynInst from the dummy nop.
- DynInstPtr instruction = new DynInst(ext_inst, PC,
- PC+sizeof(MachInst),
- inst_seq, cpu);
- instruction->setPredTarg(instruction->readNextPC());
-// instruction->setThread(tid);
-
-// instruction->setASID(tid);
-
- instruction->setState(thread);
-
- instruction->traceData = NULL;
-
- instruction->fault = fault;
- instruction->setCanIssue();
- instBuffer.push_back(instruction);
- ++instBufferSize;
-}
-
-template <class Impl>
-void
-FrontEnd<Impl>::squash(const InstSeqNum &squash_num, const Addr &next_PC,
- const bool is_branch, const bool branch_taken)
-{
- DPRINTF(FE, "Squashing from [sn:%lli], setting PC to %#x\n",
- squash_num, next_PC);
-
- if (fetchFault != NoFault)
- fetchFault = NoFault;
-
- while (!instBuffer.empty() &&
- instBuffer.back()->seqNum > squash_num) {
- DynInstPtr inst = instBuffer.back();
-
- DPRINTF(FE, "Squashing instruction [sn:%lli] PC %#x\n",
- inst->seqNum, inst->readPC());
-
- inst->clearDependents();
-
- instBuffer.pop_back();
- --instBufferSize;
-
- freeRegs+= inst->numDestRegs();
- }
-
- // Copy over rename table from the back end.
- renameTable.copyFrom(backEnd->renameTable);
-
- PC = next_PC;
-
- // Update BP with proper information.
- if (is_branch) {
- branchPred.squash(squash_num, next_PC, branch_taken, 0);
- } else {
- branchPred.squash(squash_num, 0);
- }
-
- // Clear the icache miss if it's outstanding.
- if (status == IcacheMissStall && icacheInterface) {
- DPRINTF(FE, "Squashing outstanding Icache miss.\n");
- memReq = NULL;
- }
-
- if (status == SerializeBlocked) {
- assert(barrierInst->seqNum > squash_num);
- barrierInst = NULL;
- }
-
- // Unless this squash originated from the front end, we're probably
- // in running mode now.
- // Actually might want to make this latency dependent.
- status = Running;
- fetchCacheLineNextCycle = true;
-}
-
-template <class Impl>
-typename Impl::DynInstPtr
-FrontEnd<Impl>::getInst()
-{
- if (instBufferSize == 0) {
- return NULL;
- }
-
- DynInstPtr inst = instBuffer.front();
-
- instBuffer.pop_front();
-
- --instBufferSize;
-
- dispatchCountStat++;
-
- return inst;
-}
-
-template <class Impl>
-void
-FrontEnd<Impl>::processCacheCompletion(MemReqPtr &req)
-{
- DPRINTF(FE, "Processing cache completion\n");
-
- // Do something here.
- if (status != IcacheMissStall ||
- req != memReq ||
- switchedOut) {
- DPRINTF(FE, "Previous fetch was squashed.\n");
- fetchIcacheSquashes++;
- return;
- }
-
- status = IcacheMissComplete;
-
-/* if (checkStall(tid)) {
- fetchStatus[tid] = Blocked;
- } else {
- fetchStatus[tid] = IcacheMissComplete;
- }
-*/
-// memcpy(cacheData, memReq->data, memReq->size);
-
- // Reset the completion event to NULL.
-// memReq->completionEvent = NULL;
- memReq = NULL;
-}
-
-template <class Impl>
-void
-FrontEnd<Impl>::addFreeRegs(int num_freed)
-{
- if (status == RenameBlocked && freeRegs + num_freed > 0) {
- status = Running;
- }
-
- DPRINTF(FE, "Adding %i freed registers\n", num_freed);
-
- freeRegs+= num_freed;
-
-// assert(freeRegs <= numPhysRegs);
- if (freeRegs > numPhysRegs)
- freeRegs = numPhysRegs;
-}
-
-template <class Impl>
-bool
-FrontEnd<Impl>::updateStatus()
-{
- bool serialize_block = !backEnd->robEmpty() || instBufferSize;
- bool be_block = cpu->decoupledFrontEnd ? false : backEnd->isBlocked();
- bool ret_val = false;
-
- if (status == SerializeBlocked && !serialize_block) {
- status = SerializeComplete;
- ret_val = true;
- }
-
- if (status == BEBlocked && !be_block) {
- if (barrierInst) {
- status = SerializeBlocked;
- } else {
- status = Running;
- }
- ret_val = true;
- }
- return ret_val;
-}
-
-template <class Impl>
-void
-FrontEnd<Impl>::checkBE()
-{
- bool be_block = cpu->decoupledFrontEnd ? false : backEnd->isBlocked();
- if (be_block) {
- if (status == Running || status == Idle) {
- status = BEBlocked;
- }
- }
-}
-
-template <class Impl>
-typename Impl::DynInstPtr
-FrontEnd<Impl>::getInstFromCacheline()
-{
- if (status == SerializeComplete) {
- DynInstPtr inst = barrierInst;
- status = Running;
- barrierInst = NULL;
- inst->clearSerializeBefore();
- return inst;
- }
-
- InstSeqNum inst_seq;
- MachInst inst;
- // @todo: Fix this magic number used here to handle word offset (and
- // getting rid of PAL bit)
- unsigned offset = (PC & cacheBlkMask) & ~3;
-
- // PC of inst is not in this cache block
- if (PC >= (cacheBlkPC + cacheBlkSize) || PC < cacheBlkPC || !cacheBlkValid) {
- return NULL;
- }
-
- //////////////////////////
- // Fetch one instruction
- //////////////////////////
-
- // Get a sequence number.
- inst_seq = getAndIncrementInstSeq();
-
- // Make sure this is a valid index.
- assert(offset <= cacheBlkSize - sizeof(MachInst));
-
- // Get the instruction from the array of the cache line.
- inst = htog(*reinterpret_cast<MachInst *>(&cacheData[offset]));
-
- ExtMachInst decode_inst = TheISA::makeExtMI(inst, PC);
-
- // Create a new DynInst from the instruction fetched.
- DynInstPtr instruction = new DynInst(decode_inst, PC, PC+sizeof(MachInst),
- inst_seq, cpu);
-
- instruction->setState(thread);
-
- DPRINTF(FE, "Instruction [sn:%lli] created, with PC %#x\n%s\n",
- inst_seq, instruction->readPC(),
- instruction->staticInst->disassemble(PC));
-
- instruction->traceData =
- Trace::getInstRecord(curTick, xc, cpu,
- instruction->staticInst,
- instruction->readPC(), 0);
-
- // Increment stat of fetched instructions.
- ++fetchedInsts;
-
- return instruction;
-}
-
-template <class Impl>
-void
-FrontEnd<Impl>::renameInst(DynInstPtr &inst)
-{
- DynInstPtr src_inst = NULL;
- int num_src_regs = inst->numSrcRegs();
- if (num_src_regs == 0) {
- inst->setCanIssue();
- } else {
- for (int i = 0; i < num_src_regs; ++i) {
- src_inst = renameTable[inst->srcRegIdx(i)];
-
- inst->setSrcInst(src_inst, i);
-
- DPRINTF(FE, "[sn:%lli]: Src reg %i is inst [sn:%lli]\n",
- inst->seqNum, (int)inst->srcRegIdx(i), src_inst->seqNum);
-
- if (src_inst->isResultReady()) {
- DPRINTF(FE, "Reg ready.\n");
- inst->markSrcRegReady(i);
- } else {
- DPRINTF(FE, "Adding to dependent list.\n");
- src_inst->addDependent(inst);
- }
- }
- }
-
- for (int i = 0; i < inst->numDestRegs(); ++i) {
- RegIndex idx = inst->destRegIdx(i);
-
- DPRINTF(FE, "Dest reg %i is now inst [sn:%lli], was previously "
- "[sn:%lli]\n",
- (int)inst->destRegIdx(i), inst->seqNum,
- renameTable[idx]->seqNum);
-
- inst->setPrevDestInst(renameTable[idx], i);
-
- renameTable[idx] = inst;
- --freeRegs;
- }
-}
-
-template <class Impl>
-void
-FrontEnd<Impl>::wakeFromQuiesce()
-{
- DPRINTF(FE, "Waking up from quiesce\n");
- // Hopefully this is safe
- status = Running;
-}
-
-template <class Impl>
-void
-FrontEnd<Impl>::switchOut()
-{
- switchedOut = true;
- cpu->signalSwitched();
-}
-
-template <class Impl>
-void
-FrontEnd<Impl>::doSwitchOut()
-{
- memReq = NULL;
- squash(0, 0);
- instBuffer.clear();
- instBufferSize = 0;
- status = Idle;
-}
-
-template <class Impl>
-void
-FrontEnd<Impl>::takeOverFrom(ExecContext *old_xc)
-{
- assert(freeRegs == numPhysRegs);
- fetchCacheLineNextCycle = true;
-
- cacheBlkValid = false;
-
-#if !FULL_SYSTEM
-// pTable = params->pTable;
-#endif
- fetchFault = NoFault;
- serializeNext = false;
- barrierInst = NULL;
- status = Running;
- switchedOut = false;
- interruptPending = false;
-}
-
-template <class Impl>
-void
-FrontEnd<Impl>::dumpInsts()
-{
- cprintf("instBuffer size: %i\n", instBuffer.size());
-
- InstBuffIt buff_it = instBuffer.begin();
-
- for (int num = 0; buff_it != instBuffer.end(); num++) {
- cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
- "Squashed:%i\n\n",
- num, (*buff_it)->readPC(), (*buff_it)->threadNumber,
- (*buff_it)->seqNum, (*buff_it)->isIssued(),
- (*buff_it)->isSquashed());
- buff_it++;
- }
-}
-
-template <class Impl>
-FrontEnd<Impl>::ICacheCompletionEvent::ICacheCompletionEvent(MemReqPtr &_req, FrontEnd *fe)
- : Event(&mainEventQueue, Delayed_Writeback_Pri), req(_req), frontEnd(fe)
-{
- this->setFlags(Event::AutoDelete);
-}
-
-template <class Impl>
-void
-FrontEnd<Impl>::ICacheCompletionEvent::process()
-{
- frontEnd->processCacheCompletion(req);
-}
-
-template <class Impl>
-const char *
-FrontEnd<Impl>::ICacheCompletionEvent::description()
-{
- return "ICache completion event";
-}
diff --git a/cpu/ozone/inorder_back_end.cc b/cpu/ozone/inorder_back_end.cc
deleted file mode 100644
index 14db610d2..000000000
--- a/cpu/ozone/inorder_back_end.cc
+++ /dev/null
@@ -1,5 +0,0 @@
-
-#include "cpu/ozone/inorder_back_end_impl.hh"
-#include "cpu/ozone/simple_impl.hh"
-
-template class InorderBackEnd<SimpleImpl>;
diff --git a/cpu/ozone/inorder_back_end.hh b/cpu/ozone/inorder_back_end.hh
deleted file mode 100644
index 4039d8384..000000000
--- a/cpu/ozone/inorder_back_end.hh
+++ /dev/null
@@ -1,450 +0,0 @@
-
-#ifndef __CPU_OZONE_INORDER_BACK_END_HH__
-#define __CPU_OZONE_INORDER_BACK_END_HH__
-
-#include <list>
-
-#include "arch/faults.hh"
-#include "base/timebuf.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/inst_seq.hh"
-#include "cpu/ozone/rename_table.hh"
-#include "cpu/ozone/thread_state.hh"
-#include "mem/mem_interface.hh"
-#include "mem/mem_req.hh"
-#include "sim/eventq.hh"
-
-template <class Impl>
-class InorderBackEnd
-{
- public:
- typedef typename Impl::Params Params;
- typedef typename Impl::DynInstPtr DynInstPtr;
- typedef typename Impl::FullCPU FullCPU;
- typedef typename Impl::FrontEnd FrontEnd;
-
- typedef typename FullCPU::OzoneXC OzoneXC;
- typedef typename Impl::FullCPU::CommStruct CommStruct;
-
- InorderBackEnd(Params *params);
-
- std::string name() const;
-
- void setCPU(FullCPU *cpu_ptr)
- { cpu = cpu_ptr; }
-
- void setFrontEnd(FrontEnd *front_end_ptr)
- { frontEnd = front_end_ptr; }
-
- void setCommBuffer(TimeBuffer<CommStruct> *_comm)
- { comm = _comm; }
-
- void setXC(ExecContext *xc_ptr);
-
- void setThreadState(OzoneThreadState<Impl> *thread_ptr);
-
- void regStats() { }
-
-#if FULL_SYSTEM
- void checkInterrupts();
-#endif
-
- void tick();
- void executeInsts();
- void squash(const InstSeqNum &squash_num, const Addr &next_PC);
-
- void squashFromXC();
- void generateXCEvent() { }
-
- bool robEmpty() { return instList.empty(); }
-
- bool isFull() { return false; }
- bool isBlocked() { return status == DcacheMissStoreStall ||
- status == DcacheMissLoadStall ||
- interruptBlocked; }
-
- void fetchFault(Fault &fault);
-
- void dumpInsts();
-
- private:
- void handleFault();
-
- void setSquashInfoFromXC();
-
- bool squashPending;
- InstSeqNum squashSeqNum;
- Addr squashNextPC;
-
- Fault faultFromFetch;
-
- bool interruptBlocked;
-
- public:
- template <class T>
- Fault read(Addr addr, T &data, unsigned flags);
-
- template <class T>
- Fault read(MemReqPtr &req, T &data, int load_idx);
-
- template <class T>
- Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
-
- template <class T>
- Fault write(MemReqPtr &req, T &data, int store_idx);
-
- Addr readCommitPC() { return commitPC; }
-
- Addr commitPC;
-
- void switchOut() { panic("Not implemented!"); }
- void doSwitchOut() { panic("Not implemented!"); }
- void takeOverFrom(ExecContext *old_xc = NULL) { panic("Not implemented!"); }
-
- public:
- FullCPU *cpu;
-
- FrontEnd *frontEnd;
-
- ExecContext *xc;
-
- OzoneThreadState<Impl> *thread;
-
- RenameTable<Impl> renameTable;
-
- protected:
- enum Status {
- Running,
- Idle,
- DcacheMissLoadStall,
- DcacheMissStoreStall,
- DcacheMissComplete,
- Blocked
- };
-
- Status status;
-
- class DCacheCompletionEvent : public Event
- {
- private:
- InorderBackEnd *be;
-
- public:
- DCacheCompletionEvent(InorderBackEnd *_be);
-
- virtual void process();
- virtual const char *description();
-
- DynInstPtr inst;
- };
-
- friend class DCacheCompletionEvent;
-
- DCacheCompletionEvent cacheCompletionEvent;
-
- MemInterface *dcacheInterface;
-
- MemReqPtr memReq;
-
- private:
- typedef typename std::list<DynInstPtr>::iterator InstListIt;
-
- std::list<DynInstPtr> instList;
-
- // General back end width. Used if the more specific isn't given.
- int width;
-
- int latency;
-
- int squashLatency;
-
- TimeBuffer<int> numInstsToWB;
- TimeBuffer<int>::wire instsAdded;
- TimeBuffer<int>::wire instsToExecute;
-
- TimeBuffer<CommStruct> *comm;
- // number of cycles stalled for D-cache misses
- Stats::Scalar<> dcacheStallCycles;
- Counter lastDcacheStall;
-};
-
-template <class Impl>
-template <class T>
-Fault
-InorderBackEnd<Impl>::read(Addr addr, T &data, unsigned flags)
-{
- memReq->reset(addr, sizeof(T), flags);
-
- // translate to physical address
- Fault fault = cpu->translateDataReadReq(memReq);
-
- // if we have a cache, do cache access too
- if (fault == NoFault && dcacheInterface) {
- memReq->cmd = Read;
- memReq->completionEvent = NULL;
- memReq->time = curTick;
- memReq->flags &= ~INST_READ;
- MemAccessResult result = dcacheInterface->access(memReq);
-
- // Ugly hack to get an event scheduled *only* if the access is
- // a miss. We really should add first-class support for this
- // at some point.
- if (result != MA_HIT) {
- // Fix this hack for keeping funcExeInst correct with loads that
- // are executed twice.
- memReq->completionEvent = &cacheCompletionEvent;
- lastDcacheStall = curTick;
-// unscheduleTickEvent();
- status = DcacheMissLoadStall;
- DPRINTF(IBE, "Dcache miss stall!\n");
- } else {
- // do functional access
- DPRINTF(IBE, "Dcache hit!\n");
- }
- }
-/*
- if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
- recordEvent("Uncached Read");
-*/
- return fault;
-}
-#if 0
-template <class Impl>
-template <class T>
-Fault
-InorderBackEnd<Impl>::read(MemReqPtr &req, T &data)
-{
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
- if (req->flags & LOCKED) {
- req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
- req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
- }
-#endif
-
- Fault error;
- error = thread->mem->read(req, data);
- data = LittleEndianGuest::gtoh(data);
- return error;
-}
-#endif
-
-template <class Impl>
-template <class T>
-Fault
-InorderBackEnd<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
-{
- memReq->reset(addr, sizeof(T), flags);
-
- // translate to physical address
- Fault fault = cpu->translateDataWriteReq(memReq);
-
- if (fault == NoFault && dcacheInterface) {
- memReq->cmd = Write;
-// memcpy(memReq->data,(uint8_t *)&data,memReq->size);
- memReq->completionEvent = NULL;
- memReq->time = curTick;
- memReq->flags &= ~INST_READ;
- MemAccessResult result = dcacheInterface->access(memReq);
-
- // Ugly hack to get an event scheduled *only* if the access is
- // a miss. We really should add first-class support for this
- // at some point.
- if (result != MA_HIT) {
- memReq->completionEvent = &cacheCompletionEvent;
- lastDcacheStall = curTick;
-// unscheduleTickEvent();
- status = DcacheMissStoreStall;
- DPRINTF(IBE, "Dcache miss stall!\n");
- } else {
- DPRINTF(IBE, "Dcache hit!\n");
- }
- }
-
- if (res && (fault == NoFault))
- *res = memReq->result;
-/*
- if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
- recordEvent("Uncached Write");
-*/
- return fault;
-}
-#if 0
-template <class Impl>
-template <class T>
-Fault
-InorderBackEnd<Impl>::write(MemReqPtr &req, T &data)
-{
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
- ExecContext *xc;
-
- // If this is a store conditional, act appropriately
- if (req->flags & LOCKED) {
- xc = req->xc;
-
- if (req->flags & UNCACHEABLE) {
- // Don't update result register (see stq_c in isa_desc)
- req->result = 2;
- xc->setStCondFailures(0);//Needed? [RGD]
- } else {
- bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag);
- Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag);
- req->result = lock_flag;
- if (!lock_flag ||
- ((lock_addr & ~0xf) != (req->paddr & ~0xf))) {
- xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
- xc->setStCondFailures(xc->readStCondFailures() + 1);
- if (((xc->readStCondFailures()) % 100000) == 0) {
- std::cerr << "Warning: "
- << xc->readStCondFailures()
- << " consecutive store conditional failures "
- << "on cpu " << req->xc->readCpuId()
- << std::endl;
- }
- return NoFault;
- }
- else xc->setStCondFailures(0);
- }
- }
-
- // Need to clear any locked flags on other proccessors for
- // this address. Only do this for succsful Store Conditionals
- // and all other stores (WH64?). Unsuccessful Store
- // Conditionals would have returned above, and wouldn't fall
- // through.
- for (int i = 0; i < cpu->system->execContexts.size(); i++){
- xc = cpu->system->execContexts[i];
- if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
- (req->paddr & ~0xf)) {
- xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
- }
- }
-
-#endif
- return thread->mem->write(req, (T)LittleEndianGuest::htog(data));
-}
-#endif
-
-template <class Impl>
-template <class T>
-Fault
-InorderBackEnd<Impl>::read(MemReqPtr &req, T &data, int load_idx)
-{
-// panic("Unimplemented!");
-// memReq->reset(addr, sizeof(T), flags);
-
- // translate to physical address
-// Fault fault = cpu->translateDataReadReq(req);
- req->cmd = Read;
- req->completionEvent = NULL;
- req->time = curTick;
- assert(!req->data);
- req->data = new uint8_t[64];
- req->flags &= ~INST_READ;
- Fault fault = cpu->read(req, data);
- memcpy(req->data, &data, sizeof(T));
-
- // if we have a cache, do cache access too
- if (dcacheInterface) {
- MemAccessResult result = dcacheInterface->access(req);
-
- // Ugly hack to get an event scheduled *only* if the access is
- // a miss. We really should add first-class support for this
- // at some point.
- if (result != MA_HIT) {
- req->completionEvent = &cacheCompletionEvent;
- lastDcacheStall = curTick;
-// unscheduleTickEvent();
- status = DcacheMissLoadStall;
- DPRINTF(IBE, "Dcache miss load stall!\n");
- } else {
- DPRINTF(IBE, "Dcache hit!\n");
-
- }
- }
-
-/*
- if (!dcacheInterface && (req->flags & UNCACHEABLE))
- recordEvent("Uncached Read");
-*/
- return NoFault;
-}
-
-template <class Impl>
-template <class T>
-Fault
-InorderBackEnd<Impl>::write(MemReqPtr &req, T &data, int store_idx)
-{
-// req->reset(addr, sizeof(T), flags);
-
- // translate to physical address
-// Fault fault = cpu->translateDataWriteReq(req);
-
- req->cmd = Write;
- req->completionEvent = NULL;
- req->time = curTick;
- assert(!req->data);
- req->data = new uint8_t[64];
- memcpy(req->data, (uint8_t *)&data, req->size);
-
- switch(req->size) {
- case 1:
- cpu->write(req, (uint8_t &)data);
- break;
- case 2:
- cpu->write(req, (uint16_t &)data);
- break;
- case 4:
- cpu->write(req, (uint32_t &)data);
- break;
- case 8:
- cpu->write(req, (uint64_t &)data);
- break;
- default:
- panic("Unexpected store size!\n");
- }
-
- if (dcacheInterface) {
- req->cmd = Write;
- req->data = new uint8_t[64];
- memcpy(req->data,(uint8_t *)&data,req->size);
- req->completionEvent = NULL;
- req->time = curTick;
- req->flags &= ~INST_READ;
- MemAccessResult result = dcacheInterface->access(req);
-
- // Ugly hack to get an event scheduled *only* if the access is
- // a miss. We really should add first-class support for this
- // at some point.
- if (result != MA_HIT) {
- req->completionEvent = &cacheCompletionEvent;
- lastDcacheStall = curTick;
-// unscheduleTickEvent();
- status = DcacheMissStoreStall;
- DPRINTF(IBE, "Dcache miss store stall!\n");
- } else {
- DPRINTF(IBE, "Dcache hit!\n");
-
- }
- }
-/*
- if (req->flags & LOCKED) {
- if (req->flags & UNCACHEABLE) {
- // Don't update result register (see stq_c in isa_desc)
- req->result = 2;
- } else {
- req->result = 1;
- }
- }
-*/
-/*
- if (res && (fault == NoFault))
- *res = req->result;
- */
-/*
- if (!dcacheInterface && (req->flags & UNCACHEABLE))
- recordEvent("Uncached Write");
-*/
- return NoFault;
-}
-
-#endif // __CPU_OZONE_INORDER_BACK_END_HH__
diff --git a/cpu/ozone/inorder_back_end_impl.hh b/cpu/ozone/inorder_back_end_impl.hh
deleted file mode 100644
index 5a378ec76..000000000
--- a/cpu/ozone/inorder_back_end_impl.hh
+++ /dev/null
@@ -1,519 +0,0 @@
-
-#include "arch/faults.hh"
-#include "arch/isa_traits.hh"
-#include "cpu/ozone/inorder_back_end.hh"
-#include "cpu/ozone/thread_state.hh"
-
-using namespace TheISA;
-
-template <class Impl>
-InorderBackEnd<Impl>::InorderBackEnd(Params *params)
- : squashPending(false),
- squashSeqNum(0),
- squashNextPC(0),
- faultFromFetch(NoFault),
- interruptBlocked(false),
- cacheCompletionEvent(this),
- dcacheInterface(params->dcacheInterface),
- width(params->backEndWidth),
- latency(params->backEndLatency),
- squashLatency(params->backEndSquashLatency),
- numInstsToWB(0, latency + 1)
-{
- instsAdded = numInstsToWB.getWire(latency);
- instsToExecute = numInstsToWB.getWire(0);
-
- memReq = new MemReq;
- memReq->data = new uint8_t[64];
- status = Running;
-}
-
-template <class Impl>
-std::string
-InorderBackEnd<Impl>::name() const
-{
- return cpu->name() + ".inorderbackend";
-}
-
-template <class Impl>
-void
-InorderBackEnd<Impl>::setXC(ExecContext *xc_ptr)
-{
- xc = xc_ptr;
- memReq->xc = xc;
-}
-
-template <class Impl>
-void
-InorderBackEnd<Impl>::setThreadState(OzoneThreadState<Impl> *thread_ptr)
-{
- thread = thread_ptr;
- thread->setFuncExeInst(0);
-}
-
-#if FULL_SYSTEM
-template <class Impl>
-void
-InorderBackEnd<Impl>::checkInterrupts()
-{
- //Check if there are any outstanding interrupts
- //Handle the interrupts
- int ipl = 0;
- int summary = 0;
-
- cpu->checkInterrupts = false;
-
- if (thread->readMiscReg(IPR_ASTRR))
- panic("asynchronous traps not implemented\n");
-
- if (thread->readMiscReg(IPR_SIRR)) {
- for (int i = INTLEVEL_SOFTWARE_MIN;
- i < INTLEVEL_SOFTWARE_MAX; i++) {
- if (thread->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
- // See table 4-19 of the 21164 hardware reference
- ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- uint64_t interrupts = cpu->intr_status();
-
- if (interrupts) {
- for (int i = INTLEVEL_EXTERNAL_MIN;
- i < INTLEVEL_EXTERNAL_MAX; i++) {
- if (interrupts & (ULL(1) << i)) {
- // See table 4-19 of the 21164 hardware reference
- ipl = i;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- if (ipl && ipl > thread->readMiscReg(IPR_IPLR)) {
- thread->inSyscall = true;
-
- thread->setMiscReg(IPR_ISR, summary);
- thread->setMiscReg(IPR_INTID, ipl);
- Fault(new InterruptFault)->invoke(xc);
- DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
- thread->readMiscReg(IPR_IPLR), ipl, summary);
-
- // May need to go 1 inst prior
- squashPending = true;
-
- thread->inSyscall = false;
-
- setSquashInfoFromXC();
- }
-}
-#endif
-
-template <class Impl>
-void
-InorderBackEnd<Impl>::tick()
-{
- // Squash due to an external source
- // Not sure if this or an interrupt has higher priority
- if (squashPending) {
- squash(squashSeqNum, squashNextPC);
- return;
- }
-
- // if (interrupt) then set thread PC, stall front end, record that
- // I'm waiting for it to drain. (for now just squash)
-#if FULL_SYSTEM
- if (interruptBlocked ||
- (cpu->checkInterrupts &&
- cpu->check_interrupts() &&
- !cpu->inPalMode())) {
- if (!robEmpty()) {
- interruptBlocked = true;
- } else if (robEmpty() && cpu->inPalMode()) {
- // Will need to let the front end continue a bit until
- // we're out of pal mode. Hopefully we never get into an
- // infinite loop...
- interruptBlocked = false;
- } else {
- interruptBlocked = false;
- checkInterrupts();
- return;
- }
- }
-#endif
-
- if (status != DcacheMissLoadStall &&
- status != DcacheMissStoreStall) {
- for (int i = 0; i < width && (*instsAdded) < width; ++i) {
- DynInstPtr inst = frontEnd->getInst();
-
- if (!inst)
- break;
-
- instList.push_back(inst);
-
- (*instsAdded)++;
- }
-
-#if FULL_SYSTEM
- if (faultFromFetch && robEmpty() && frontEnd->isEmpty()) {
- handleFault();
- } else {
- executeInsts();
- }
-#else
- executeInsts();
-#endif
- }
-}
-
-template <class Impl>
-void
-InorderBackEnd<Impl>::executeInsts()
-{
- bool completed_last_inst = true;
- int insts_to_execute = *instsToExecute;
- int freed_regs = 0;
-
- while (insts_to_execute > 0) {
- assert(!instList.empty());
- DynInstPtr inst = instList.front();
-
- commitPC = inst->readPC();
-
- thread->setPC(commitPC);
- thread->setNextPC(inst->readNextPC());
-
-#if FULL_SYSTEM
- int count = 0;
- Addr oldpc;
- do {
- if (count == 0)
- assert(!thread->inSyscall && !thread->trapPending);
- oldpc = thread->readPC();
- cpu->system->pcEventQueue.service(
- thread->getXCProxy());
- count++;
- } while (oldpc != thread->readPC());
- if (count > 1) {
- DPRINTF(IBE, "PC skip function event, stopping commit\n");
- completed_last_inst = false;
- squashPending = true;
- break;
- }
-#endif
-
- Fault inst_fault = NoFault;
-
- if (status == DcacheMissComplete) {
- DPRINTF(IBE, "Completing inst [sn:%lli]\n", inst->seqNum);
- status = Running;
- } else if (inst->isMemRef() && status != DcacheMissComplete &&
- (!inst->isDataPrefetch() && !inst->isInstPrefetch())) {
- DPRINTF(IBE, "Initiating mem op inst [sn:%lli] PC: %#x\n",
- inst->seqNum, inst->readPC());
-
- cacheCompletionEvent.inst = inst;
- inst_fault = inst->initiateAcc();
- if (inst_fault == NoFault &&
- status != DcacheMissLoadStall &&
- status != DcacheMissStoreStall) {
- inst_fault = inst->completeAcc();
- }
- ++thread->funcExeInst;
- } else {
- DPRINTF(IBE, "Executing inst [sn:%lli] PC: %#x\n",
- inst->seqNum, inst->readPC());
- inst_fault = inst->execute();
- ++thread->funcExeInst;
- }
-
- // Will need to be able to break this loop in case the load
- // misses. Split access/complete ops would be useful here
- // with writeback events.
- if (status == DcacheMissLoadStall) {
- *instsToExecute = insts_to_execute;
-
- completed_last_inst = false;
- break;
- } else if (status == DcacheMissStoreStall) {
- // Figure out how to fix this hack. Probably have DcacheMissLoad
- // vs DcacheMissStore.
- *instsToExecute = insts_to_execute;
- completed_last_inst = false;
-/*
- instList.pop_front();
- --insts_to_execute;
- if (inst->traceData) {
- inst->traceData->finalize();
- }
-*/
-
- // Don't really need to stop for a store stall as long as
- // the memory system is able to handle store forwarding
- // and such. Breaking out might help avoid the cache
- // interface becoming blocked.
- break;
- }
-
- inst->setExecuted();
- inst->setCompleted();
- inst->setCanCommit();
-
- instList.pop_front();
-
- --insts_to_execute;
- --(*instsToExecute);
-
- if (inst->traceData) {
- inst->traceData->finalize();
- inst->traceData = NULL;
- }
-
- if (inst_fault != NoFault) {
-#if FULL_SYSTEM
- DPRINTF(IBE, "Inst [sn:%lli] PC %#x has a fault\n",
- inst->seqNum, inst->readPC());
-
- assert(!thread->inSyscall);
-
- thread->inSyscall = true;
-
- // Hack for now; DTB will sometimes need the machine instruction
- // for when faults happen. So we will set it here, prior to the
- // DTB possibly needing it for this translation.
- thread->setInst(
- static_cast<TheISA::MachInst>(inst->staticInst->machInst));
-
- // Consider holding onto the trap and waiting until the trap event
- // happens for this to be executed.
- inst_fault->invoke(xc);
-
- // Exit state update mode to avoid accidental updating.
- thread->inSyscall = false;
-
- squashPending = true;
-
- // Generate trap squash event.
-// generateTrapEvent(tid);
- completed_last_inst = false;
- break;
-#else // !FULL_SYSTEM
- panic("fault (%d) detected @ PC %08p", inst_fault,
- inst->PC);
-#endif // FULL_SYSTEM
- }
-
- for (int i = 0; i < inst->numDestRegs(); ++i) {
- renameTable[inst->destRegIdx(i)] = inst;
- thread->renameTable[inst->destRegIdx(i)] = inst;
- ++freed_regs;
- }
-
- inst->clearDependents();
-
- comm->access(0)->doneSeqNum = inst->seqNum;
-
- if (inst->mispredicted()) {
- squash(inst->seqNum, inst->readNextPC());
-
- thread->setNextPC(inst->readNextPC());
-
- break;
- } else if (squashPending) {
- // Something external happened that caused the CPU to squash.
- // Break out of commit and handle the squash next cycle.
- break;
- }
- // If it didn't mispredict, then it executed fine. Send back its
- // registers and BP info? What about insts that may still have
- // latency, like loads? Probably can send back the information after
- // it is completed.
-
- // keep an instruction count
- cpu->numInst++;
- thread->numInsts++;
- }
-
- frontEnd->addFreeRegs(freed_regs);
-
- assert(insts_to_execute >= 0);
-
- // Should only advance this if I have executed all instructions.
- if (insts_to_execute == 0) {
- numInstsToWB.advance();
- }
-
- // Should I set the PC to the next PC here? What do I set next PC to?
- if (completed_last_inst) {
- thread->setPC(thread->readNextPC());
- thread->setNextPC(thread->readPC() + sizeof(MachInst));
- }
-
- if (squashPending) {
- setSquashInfoFromXC();
- }
-}
-
-template <class Impl>
-void
-InorderBackEnd<Impl>::handleFault()
-{
- DPRINTF(Commit, "Handling fault from fetch\n");
-
- assert(!thread->inSyscall);
-
- thread->inSyscall = true;
-
- // Consider holding onto the trap and waiting until the trap event
- // happens for this to be executed.
- faultFromFetch->invoke(xc);
-
- // Exit state update mode to avoid accidental updating.
- thread->inSyscall = false;
-
- squashPending = true;
-
- setSquashInfoFromXC();
-}
-
-template <class Impl>
-void
-InorderBackEnd<Impl>::squash(const InstSeqNum &squash_num, const Addr &next_PC)
-{
- DPRINTF(IBE, "Squashing from [sn:%lli], setting PC to %#x\n",
- squash_num, next_PC);
-
- InstListIt squash_it = --(instList.end());
-
- int freed_regs = 0;
-
- while (!instList.empty() && (*squash_it)->seqNum > squash_num) {
- DynInstPtr inst = *squash_it;
-
- DPRINTF(IBE, "Squashing instruction PC %#x, [sn:%lli].\n",
- inst->readPC(),
- inst->seqNum);
-
- // May cause problems with misc regs
- freed_regs+= inst->numDestRegs();
- inst->clearDependents();
- squash_it--;
- instList.pop_back();
- }
-
- frontEnd->addFreeRegs(freed_regs);
-
- for (int i = 0; i < latency+1; ++i) {
- numInstsToWB.advance();
- }
-
- squashPending = false;
-
- // Probably want to make sure that this squash is the one that set the
- // thread into inSyscall mode.
- thread->inSyscall = false;
-
- // Tell front end to squash, reset PC to new one.
- frontEnd->squash(squash_num, next_PC);
-
- faultFromFetch = NULL;
-}
-
-template <class Impl>
-void
-InorderBackEnd<Impl>::squashFromXC()
-{
- // Record that I need to squash
- squashPending = true;
-
- thread->inSyscall = true;
-}
-
-template <class Impl>
-void
-InorderBackEnd<Impl>::setSquashInfoFromXC()
-{
- // Need to handle the case of the instList being empty. In that case
- // probably any number works, except maybe with stores in the store buffer.
- squashSeqNum = instList.empty() ? 0 : instList.front()->seqNum - 1;
-
- squashNextPC = thread->PC;
-}
-
-template <class Impl>
-void
-InorderBackEnd<Impl>::fetchFault(Fault &fault)
-{
- faultFromFetch = fault;
-}
-
-template <class Impl>
-void
-InorderBackEnd<Impl>::dumpInsts()
-{
- int num = 0;
- int valid_num = 0;
-
- InstListIt inst_list_it = instList.begin();
-
- cprintf("Inst list size: %i\n", instList.size());
-
- while (inst_list_it != instList.end())
- {
- cprintf("Instruction:%i\n",
- num);
- if (!(*inst_list_it)->isSquashed()) {
- if (!(*inst_list_it)->isIssued()) {
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- } else if ((*inst_list_it)->isMemRef() &&
- !(*inst_list_it)->memOpDone) {
- // Loads that have not been marked as executed still count
- // towards the total instructions.
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- }
- }
-
- cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
- "Issued:%i\nSquashed:%i\n",
- (*inst_list_it)->readPC(),
- (*inst_list_it)->seqNum,
- (*inst_list_it)->threadNumber,
- (*inst_list_it)->isIssued(),
- (*inst_list_it)->isSquashed());
-
- if ((*inst_list_it)->isMemRef()) {
- cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
- }
-
- cprintf("\n");
-
- inst_list_it++;
- ++num;
- }
-}
-
-template <class Impl>
-InorderBackEnd<Impl>::DCacheCompletionEvent::DCacheCompletionEvent(
- InorderBackEnd *_be)
- : Event(&mainEventQueue, CPU_Tick_Pri), be(_be)
-{
-// this->setFlags(Event::AutoDelete);
-}
-
-template <class Impl>
-void
-InorderBackEnd<Impl>::DCacheCompletionEvent::process()
-{
- inst->completeAcc();
- be->status = DcacheMissComplete;
-}
-
-template <class Impl>
-const char *
-InorderBackEnd<Impl>::DCacheCompletionEvent::description()
-{
- return "DCache completion event";
-}
diff --git a/cpu/ozone/inst_queue.cc b/cpu/ozone/inst_queue.cc
deleted file mode 100644
index 9c61602d9..000000000
--- a/cpu/ozone/inst_queue.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/ozone/dyn_inst.hh"
-#include "cpu/ozone/ozone_impl.hh"
-#include "cpu/ozone/simple_impl.hh"
-#include "cpu/ozone/inst_queue_impl.hh"
-
-// Force instantiation of InstructionQueue.
-template class InstQueue<SimpleImpl>;
-template class InstQueue<OzoneImpl>;
diff --git a/cpu/ozone/inst_queue.hh b/cpu/ozone/inst_queue.hh
deleted file mode 100644
index 2cbbb7987..000000000
--- a/cpu/ozone/inst_queue.hh
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_OZONE_INST_QUEUE_HH__
-#define __CPU_OZONE_INST_QUEUE_HH__
-
-#include <list>
-#include <map>
-#include <queue>
-#include <vector>
-
-#include "base/statistics.hh"
-#include "base/timebuf.hh"
-#include "cpu/inst_seq.hh"
-#include "sim/host.hh"
-
-class FUPool;
-class MemInterface;
-
-/**
- * A standard instruction queue class. It holds ready instructions, in
- * order, in seperate priority queues to facilitate the scheduling of
- * instructions. The IQ uses a separate linked list to track dependencies.
- * Similar to the rename map and the free list, it expects that
- * floating point registers have their indices start after the integer
- * registers (ie with 96 int and 96 fp registers, regs 0-95 are integer
- * and 96-191 are fp). This remains true even for both logical and
- * physical register indices. The IQ depends on the memory dependence unit to
- * track when memory operations are ready in terms of ordering; register
- * dependencies are tracked normally. Right now the IQ also handles the
- * execution timing; this is mainly to allow back-to-back scheduling without
- * requiring IEW to be able to peek into the IQ. At the end of the execution
- * latency, the instruction is put into the queue to execute, where it will
- * have the execute() function called on it.
- * @todo: Make IQ able to handle multiple FU pools.
- */
-template <class Impl>
-class InstQueue
-{
- public:
- //Typedefs from the Impl.
- typedef typename Impl::FullCPU FullCPU;
- typedef typename Impl::DynInstPtr DynInstPtr;
- typedef typename Impl::Params Params;
- typedef typename Impl::IssueStruct IssueStruct;
-/*
- typedef typename Impl::CPUPol::IEW IEW;
- typedef typename Impl::CPUPol::MemDepUnit MemDepUnit;
- typedef typename Impl::CPUPol::IssueStruct IssueStruct;
- typedef typename Impl::CPUPol::TimeStruct TimeStruct;
-*/
- // Typedef of iterator through the list of instructions.
- typedef typename std::list<DynInstPtr>::iterator ListIt;
-
- friend class Impl::FullCPU;
-#if 0
- /** FU completion event class. */
- class FUCompletion : public Event {
- private:
- /** Executing instruction. */
- DynInstPtr inst;
-
- /** Index of the FU used for executing. */
- int fuIdx;
-
- /** Pointer back to the instruction queue. */
- InstQueue<Impl> *iqPtr;
-
- public:
- /** Construct a FU completion event. */
- FUCompletion(DynInstPtr &_inst, int fu_idx,
- InstQueue<Impl> *iq_ptr);
-
- virtual void process();
- virtual const char *description();
- };
-#endif
- /** Constructs an IQ. */
- InstQueue(Params *params);
-
- /** Destructs the IQ. */
- ~InstQueue();
-
- /** Returns the name of the IQ. */
- std::string name() const;
-
- /** Registers statistics. */
- void regStats();
-
- /** Sets CPU pointer. */
- void setCPU(FullCPU *_cpu) { cpu = _cpu; }
-#if 0
- /** Sets active threads list. */
- void setActiveThreads(list<unsigned> *at_ptr);
-
- /** Sets the IEW pointer. */
- void setIEW(IEW *iew_ptr) { iewStage = iew_ptr; }
-#endif
- /** Sets the timer buffer between issue and execute. */
- void setIssueToExecuteQueue(TimeBuffer<IssueStruct> *i2eQueue);
-#if 0
- /** Sets the global time buffer. */
- void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
-
- /** Number of entries needed for given amount of threads. */
- int entryAmount(int num_threads);
-
- /** Resets max entries for all threads. */
- void resetEntries();
-#endif
- /** Returns total number of free entries. */
- unsigned numFreeEntries();
-
- /** Returns number of free entries for a thread. */
- unsigned numFreeEntries(unsigned tid);
-
- /** Returns whether or not the IQ is full. */
- bool isFull();
-
- /** Returns whether or not the IQ is full for a specific thread. */
- bool isFull(unsigned tid);
-
- /** Returns if there are any ready instructions in the IQ. */
- bool hasReadyInsts();
-
- /** Inserts a new instruction into the IQ. */
- void insert(DynInstPtr &new_inst);
-
- /** Inserts a new, non-speculative instruction into the IQ. */
- void insertNonSpec(DynInstPtr &new_inst);
-#if 0
- /**
- * Advances the tail of the IQ, used if an instruction is not added to the
- * IQ for scheduling.
- * @todo: Rename this function.
- */
- void advanceTail(DynInstPtr &inst);
-
- /** Process FU completion event. */
- void processFUCompletion(DynInstPtr &inst, int fu_idx);
-#endif
- /**
- * Schedules ready instructions, adding the ready ones (oldest first) to
- * the queue to execute.
- */
- void scheduleReadyInsts();
-
- /** Schedules a single specific non-speculative instruction. */
- void scheduleNonSpec(const InstSeqNum &inst);
-
- /**
- * Commits all instructions up to and including the given sequence number,
- * for a specific thread.
- */
- void commit(const InstSeqNum &inst, unsigned tid = 0);
-
- /** Wakes all dependents of a completed instruction. */
- void wakeDependents(DynInstPtr &completed_inst);
-
- /** Adds a ready memory instruction to the ready list. */
- void addReadyMemInst(DynInstPtr &ready_inst);
-#if 0
- /**
- * Reschedules a memory instruction. It will be ready to issue once
- * replayMemInst() is called.
- */
- void rescheduleMemInst(DynInstPtr &resched_inst);
-
- /** Replays a memory instruction. It must be rescheduled first. */
- void replayMemInst(DynInstPtr &replay_inst);
-#endif
- /** Completes a memory operation. */
- void completeMemInst(DynInstPtr &completed_inst);
-#if 0
- /** Indicates an ordering violation between a store and a load. */
- void violation(DynInstPtr &store, DynInstPtr &faulting_load);
-#endif
- /**
- * Squashes instructions for a thread. Squashing information is obtained
- * from the time buffer.
- */
- void squash(unsigned tid); // Probably want the ISN
-
- /** Returns the number of used entries for a thread. */
- unsigned getCount(unsigned tid) { return count[tid]; };
-
- /** Updates the number of free entries. */
- void updateFreeEntries(int num) { freeEntries += num; }
-
- /** Debug function to print all instructions. */
- void printInsts();
-
- private:
- /** Does the actual squashing. */
- void doSquash(unsigned tid);
-
- /////////////////////////
- // Various pointers
- /////////////////////////
-
- /** Pointer to the CPU. */
- FullCPU *cpu;
-
- /** Cache interface. */
- MemInterface *dcacheInterface;
-#if 0
- /** Pointer to IEW stage. */
- IEW *iewStage;
-
- /** The memory dependence unit, which tracks/predicts memory dependences
- * between instructions.
- */
- MemDepUnit memDepUnit[Impl::MaxThreads];
-#endif
- /** The queue to the execute stage. Issued instructions will be written
- * into it.
- */
- TimeBuffer<IssueStruct> *issueToExecuteQueue;
-#if 0
- /** The backwards time buffer. */
- TimeBuffer<TimeStruct> *timeBuffer;
-
- /** Wire to read information from timebuffer. */
- typename TimeBuffer<TimeStruct>::wire fromCommit;
-
- /** Function unit pool. */
- FUPool *fuPool;
-#endif
- //////////////////////////////////////
- // Instruction lists, ready queues, and ordering
- //////////////////////////////////////
-
- /** List of all the instructions in the IQ (some of which may be issued). */
- std::list<DynInstPtr> instList[Impl::MaxThreads];
-
- /**
- * Struct for comparing entries to be added to the priority queue. This
- * gives reverse ordering to the instructions in terms of sequence
- * numbers: the instructions with smaller sequence numbers (and hence
- * are older) will be at the top of the priority queue.
- */
- struct pqCompare {
- bool operator() (const DynInstPtr &lhs, const DynInstPtr &rhs) const
- {
- return lhs->seqNum > rhs->seqNum;
- }
- };
-
- /**
- * Struct for an IQ entry. It includes the instruction and an iterator
- * to the instruction's spot in the IQ.
- */
- struct IQEntry {
- DynInstPtr inst;
- ListIt iqIt;
- };
-
- typedef std::priority_queue<DynInstPtr, std::vector<DynInstPtr>, pqCompare>
- ReadyInstQueue;
-
- typedef std::map<DynInstPtr, pqCompare> ReadyInstMap;
- typedef typename std::map<DynInstPtr, pqCompare>::iterator ReadyMapIt;
-
- /** List of ready instructions.
- */
- ReadyInstQueue readyInsts;
-
- /** List of non-speculative instructions that will be scheduled
- * once the IQ gets a signal from commit. While it's redundant to
- * have the key be a part of the value (the sequence number is stored
- * inside of DynInst), when these instructions are woken up only
- * the sequence number will be available. Thus it is most efficient to be
- * able to search by the sequence number alone.
- */
- std::map<InstSeqNum, DynInstPtr> nonSpecInsts;
-
- typedef typename std::map<InstSeqNum, DynInstPtr>::iterator NonSpecMapIt;
-#if 0
- /** Entry for the list age ordering by op class. */
- struct ListOrderEntry {
- OpClass queueType;
- InstSeqNum oldestInst;
- };
-
- /** List that contains the age order of the oldest instruction of each
- * ready queue. Used to select the oldest instruction available
- * among op classes.
- */
- std::list<ListOrderEntry> listOrder;
-
- typedef typename std::list<ListOrderEntry>::iterator ListOrderIt;
-
- /** Tracks if each ready queue is on the age order list. */
- bool queueOnList[Num_OpClasses];
-
- /** Iterators of each ready queue. Points to their spot in the age order
- * list.
- */
- ListOrderIt readyIt[Num_OpClasses];
-
- /** Add an op class to the age order list. */
- void addToOrderList(OpClass op_class);
-
- /**
- * Called when the oldest instruction has been removed from a ready queue;
- * this places that ready queue into the proper spot in the age order list.
- */
- void moveToYoungerInst(ListOrderIt age_order_it);
-#endif
- //////////////////////////////////////
- // Various parameters
- //////////////////////////////////////
-#if 0
- /** IQ Resource Sharing Policy */
- enum IQPolicy {
- Dynamic,
- Partitioned,
- Threshold
- };
-
- /** IQ sharing policy for SMT. */
- IQPolicy iqPolicy;
-#endif
- /** Number of Total Threads*/
- unsigned numThreads;
-#if 0
- /** Pointer to list of active threads. */
- list<unsigned> *activeThreads;
-#endif
- /** Per Thread IQ count */
- unsigned count[Impl::MaxThreads];
-
- /** Max IQ Entries Per Thread */
- unsigned maxEntries[Impl::MaxThreads];
-
- /** Number of free IQ entries left. */
- unsigned freeEntries;
-
- /** The number of entries in the instruction queue. */
- unsigned numEntries;
-
- /** The total number of instructions that can be issued in one cycle. */
- unsigned totalWidth;
-#if 0
- /** The number of physical registers in the CPU. */
- unsigned numPhysRegs;
-
- /** The number of physical integer registers in the CPU. */
- unsigned numPhysIntRegs;
-
- /** The number of floating point registers in the CPU. */
- unsigned numPhysFloatRegs;
-#endif
- /** Delay between commit stage and the IQ.
- * @todo: Make there be a distinction between the delays within IEW.
- */
- unsigned commitToIEWDelay;
-
- //////////////////////////////////
- // Variables needed for squashing
- //////////////////////////////////
-
- /** The sequence number of the squashed instruction. */
- InstSeqNum squashedSeqNum[Impl::MaxThreads];
-
- /** Iterator that points to the last instruction that has been squashed.
- * This will not be valid unless the IQ is in the process of squashing.
- */
- ListIt squashIt[Impl::MaxThreads];
-#if 0
- ///////////////////////////////////
- // Dependency graph stuff
- ///////////////////////////////////
-
- class DependencyEntry
- {
- public:
- DependencyEntry()
- : inst(NULL), next(NULL)
- { }
-
- DynInstPtr inst;
- //Might want to include data about what arch. register the
- //dependence is waiting on.
- DependencyEntry *next;
-
- //This function, and perhaps this whole class, stand out a little
- //bit as they don't fit a classification well. I want access
- //to the underlying structure of the linked list, yet at
- //the same time it feels like this should be something abstracted
- //away. So for now it will sit here, within the IQ, until
- //a better implementation is decided upon.
- // This function probably shouldn't be within the entry...
- void insert(DynInstPtr &new_inst);
-
- void remove(DynInstPtr &inst_to_remove);
-
- // Debug variable, remove when done testing.
- static unsigned mem_alloc_counter;
- };
-
- /** Array of linked lists. Each linked list is a list of all the
- * instructions that depend upon a given register. The actual
- * register's index is used to index into the graph; ie all
- * instructions in flight that are dependent upon r34 will be
- * in the linked list of dependGraph[34].
- */
- DependencyEntry *dependGraph;
-
- /** A cache of the recently woken registers. It is 1 if the register
- * has been woken up recently, and 0 if the register has been added
- * to the dependency graph and has not yet received its value. It
- * is basically a secondary scoreboard, and should pretty much mirror
- * the scoreboard that exists in the rename map.
- */
- vector<bool> regScoreboard;
-
- /** Adds an instruction to the dependency graph, as a producer. */
- bool addToDependents(DynInstPtr &new_inst);
-
- /** Adds an instruction to the dependency graph, as a consumer. */
- void createDependency(DynInstPtr &new_inst);
-#endif
- /** Moves an instruction to the ready queue if it is ready. */
- void addIfReady(DynInstPtr &inst);
-
- /** Debugging function to count how many entries are in the IQ. It does
- * a linear walk through the instructions, so do not call this function
- * during normal execution.
- */
- int countInsts();
-#if 0
- /** Debugging function to dump out the dependency graph.
- */
- void dumpDependGraph();
-#endif
- /** Debugging function to dump all the list sizes, as well as print
- * out the list of nonspeculative instructions. Should not be used
- * in any other capacity, but it has no harmful sideaffects.
- */
- void dumpLists();
-
- /** Debugging function to dump out all instructions that are in the
- * IQ.
- */
- void dumpInsts();
-
- /** Stat for number of instructions added. */
- Stats::Scalar<> iqInstsAdded;
- /** Stat for number of non-speculative instructions added. */
- Stats::Scalar<> iqNonSpecInstsAdded;
-// Stats::Scalar<> iqIntInstsAdded;
- /** Stat for number of integer instructions issued. */
- Stats::Scalar<> iqIntInstsIssued;
-// Stats::Scalar<> iqFloatInstsAdded;
- /** Stat for number of floating point instructions issued. */
- Stats::Scalar<> iqFloatInstsIssued;
-// Stats::Scalar<> iqBranchInstsAdded;
- /** Stat for number of branch instructions issued. */
- Stats::Scalar<> iqBranchInstsIssued;
-// Stats::Scalar<> iqMemInstsAdded;
- /** Stat for number of memory instructions issued. */
- Stats::Scalar<> iqMemInstsIssued;
-// Stats::Scalar<> iqMiscInstsAdded;
- /** Stat for number of miscellaneous instructions issued. */
- Stats::Scalar<> iqMiscInstsIssued;
- /** Stat for number of squashed instructions that were ready to issue. */
- Stats::Scalar<> iqSquashedInstsIssued;
- /** Stat for number of squashed instructions examined when squashing. */
- Stats::Scalar<> iqSquashedInstsExamined;
- /** Stat for number of squashed instruction operands examined when
- * squashing.
- */
- Stats::Scalar<> iqSquashedOperandsExamined;
- /** Stat for number of non-speculative instructions removed due to a squash.
- */
- Stats::Scalar<> iqSquashedNonSpecRemoved;
-
-};
-
-#endif //__CPU_OZONE_INST_QUEUE_HH__
diff --git a/cpu/ozone/inst_queue_impl.hh b/cpu/ozone/inst_queue_impl.hh
deleted file mode 100644
index 0523c68d6..000000000
--- a/cpu/ozone/inst_queue_impl.hh
+++ /dev/null
@@ -1,1341 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-// Todo:
-// Current ordering allows for 0 cycle added-to-scheduled. Could maybe fake
-// it; either do in reverse order, or have added instructions put into a
-// different ready queue that, in scheduleRreadyInsts(), gets put onto the
-// normal ready queue. This would however give only a one cycle delay,
-// but probably is more flexible to actually add in a delay parameter than
-// just running it backwards.
-
-#include <vector>
-
-#include "sim/root.hh"
-
-#include "cpu/ozone/inst_queue.hh"
-#if 0
-template <class Impl>
-InstQueue<Impl>::FUCompletion::FUCompletion(DynInstPtr &_inst,
- int fu_idx,
- InstQueue<Impl> *iq_ptr)
- : Event(&mainEventQueue, Stat_Event_Pri),
- inst(_inst), fuIdx(fu_idx), iqPtr(iq_ptr)
-{
- this->setFlags(Event::AutoDelete);
-}
-
-template <class Impl>
-void
-InstQueue<Impl>::FUCompletion::process()
-{
- iqPtr->processFUCompletion(inst, fuIdx);
-}
-
-
-template <class Impl>
-const char *
-InstQueue<Impl>::FUCompletion::description()
-{
- return "Functional unit completion event";
-}
-#endif
-template <class Impl>
-InstQueue<Impl>::InstQueue(Params *params)
- : dcacheInterface(params->dcacheInterface),
-// fuPool(params->fuPool),
- numEntries(params->numIQEntries),
- totalWidth(params->issueWidth),
-// numPhysIntRegs(params->numPhysIntRegs),
-// numPhysFloatRegs(params->numPhysFloatRegs),
- commitToIEWDelay(params->commitToIEWDelay)
-{
-// assert(fuPool);
-
-// numThreads = params->numberOfThreads;
- numThreads = 1;
-
- //Initialize thread IQ counts
- for (int i = 0; i <numThreads; i++) {
- count[i] = 0;
- }
-
- // Initialize the number of free IQ entries.
- freeEntries = numEntries;
-
- // Set the number of physical registers as the number of int + float
-// numPhysRegs = numPhysIntRegs + numPhysFloatRegs;
-
-// DPRINTF(IQ, "There are %i physical registers.\n", numPhysRegs);
-
- //Create an entry for each physical register within the
- //dependency graph.
-// dependGraph = new DependencyEntry[numPhysRegs];
-
- // Resize the register scoreboard.
-// regScoreboard.resize(numPhysRegs);
-/*
- //Initialize Mem Dependence Units
- for (int i = 0; i < numThreads; i++) {
- memDepUnit[i].init(params,i);
- memDepUnit[i].setIQ(this);
- }
-
- // Initialize all the head pointers to point to NULL, and all the
- // entries as unready.
- // Note that in actuality, the registers corresponding to the logical
- // registers start off as ready. However this doesn't matter for the
- // IQ as the instruction should have been correctly told if those
- // registers are ready in rename. Thus it can all be initialized as
- // unready.
- for (int i = 0; i < numPhysRegs; ++i) {
- dependGraph[i].next = NULL;
- dependGraph[i].inst = NULL;
- regScoreboard[i] = false;
- }
-*/
- for (int i = 0; i < numThreads; ++i) {
- squashedSeqNum[i] = 0;
- }
-/*
- for (int i = 0; i < Num_OpClasses; ++i) {
- queueOnList[i] = false;
- readyIt[i] = listOrder.end();
- }
-
- string policy = params->smtIQPolicy;
-
- //Convert string to lowercase
- std::transform(policy.begin(), policy.end(), policy.begin(),
- (int(*)(int)) tolower);
-
- //Figure out resource sharing policy
- if (policy == "dynamic") {
- iqPolicy = Dynamic;
-
- //Set Max Entries to Total ROB Capacity
- for (int i = 0; i < numThreads; i++) {
- maxEntries[i] = numEntries;
- }
-
- } else if (policy == "partitioned") {
- iqPolicy = Partitioned;
-
- //@todo:make work if part_amt doesnt divide evenly.
- int part_amt = numEntries / numThreads;
-
- //Divide ROB up evenly
- for (int i = 0; i < numThreads; i++) {
- maxEntries[i] = part_amt;
- }
-
- DPRINTF(Fetch, "IQ sharing policy set to Partitioned:"
- "%i entries per thread.\n",part_amt);
-
- } else if (policy == "threshold") {
- iqPolicy = Threshold;
-
- double threshold = (double)params->smtIQThreshold / 100;
-
- int thresholdIQ = (int)((double)threshold * numEntries);
-
- //Divide up by threshold amount
- for (int i = 0; i < numThreads; i++) {
- maxEntries[i] = thresholdIQ;
- }
-
- DPRINTF(Fetch, "IQ sharing policy set to Threshold:"
- "%i entries per thread.\n",thresholdIQ);
- } else {
- assert(0 && "Invalid IQ Sharing Policy.Options Are:{Dynamic,"
- "Partitioned, Threshold}");
- }
-*/
-}
-
-template <class Impl>
-InstQueue<Impl>::~InstQueue()
-{
- // Clear the dependency graph
-/*
- DependencyEntry *curr;
- DependencyEntry *prev;
-
- for (int i = 0; i < numPhysRegs; ++i) {
- curr = dependGraph[i].next;
-
- while (curr) {
- DependencyEntry::mem_alloc_counter--;
-
- prev = curr;
- curr = prev->next;
- prev->inst = NULL;
-
- delete prev;
- }
-
- if (dependGraph[i].inst) {
- dependGraph[i].inst = NULL;
- }
-
- dependGraph[i].next = NULL;
- }
-
- assert(DependencyEntry::mem_alloc_counter == 0);
-
- delete [] dependGraph;
-*/
-}
-
-template <class Impl>
-std::string
-InstQueue<Impl>::name() const
-{
- return cpu->name() + ".iq";
-}
-
-template <class Impl>
-void
-InstQueue<Impl>::regStats()
-{
- iqInstsAdded
- .name(name() + ".iqInstsAdded")
- .desc("Number of instructions added to the IQ (excludes non-spec)")
- .prereq(iqInstsAdded);
-
- iqNonSpecInstsAdded
- .name(name() + ".iqNonSpecInstsAdded")
- .desc("Number of non-speculative instructions added to the IQ")
- .prereq(iqNonSpecInstsAdded);
-
-// iqIntInstsAdded;
-
- iqIntInstsIssued
- .name(name() + ".iqIntInstsIssued")
- .desc("Number of integer instructions issued")
- .prereq(iqIntInstsIssued);
-
-// iqFloatInstsAdded;
-
- iqFloatInstsIssued
- .name(name() + ".iqFloatInstsIssued")
- .desc("Number of float instructions issued")
- .prereq(iqFloatInstsIssued);
-
-// iqBranchInstsAdded;
-
- iqBranchInstsIssued
- .name(name() + ".iqBranchInstsIssued")
- .desc("Number of branch instructions issued")
- .prereq(iqBranchInstsIssued);
-
-// iqMemInstsAdded;
-
- iqMemInstsIssued
- .name(name() + ".iqMemInstsIssued")
- .desc("Number of memory instructions issued")
- .prereq(iqMemInstsIssued);
-
-// iqMiscInstsAdded;
-
- iqMiscInstsIssued
- .name(name() + ".iqMiscInstsIssued")
- .desc("Number of miscellaneous instructions issued")
- .prereq(iqMiscInstsIssued);
-
- iqSquashedInstsIssued
- .name(name() + ".iqSquashedInstsIssued")
- .desc("Number of squashed instructions issued")
- .prereq(iqSquashedInstsIssued);
-
- iqSquashedInstsExamined
- .name(name() + ".iqSquashedInstsExamined")
- .desc("Number of squashed instructions iterated over during squash;"
- " mainly for profiling")
- .prereq(iqSquashedInstsExamined);
-
- iqSquashedOperandsExamined
- .name(name() + ".iqSquashedOperandsExamined")
- .desc("Number of squashed operands that are examined and possibly "
- "removed from graph")
- .prereq(iqSquashedOperandsExamined);
-
- iqSquashedNonSpecRemoved
- .name(name() + ".iqSquashedNonSpecRemoved")
- .desc("Number of squashed non-spec instructions that were removed")
- .prereq(iqSquashedNonSpecRemoved);
-/*
- for ( int i=0; i < numThreads; i++) {
- // Tell mem dependence unit to reg stats as well.
- memDepUnit[i].regStats();
- }
-*/
-}
-/*
-template <class Impl>
-void
-InstQueue<Impl>::setActiveThreads(list<unsigned> *at_ptr)
-{
- DPRINTF(IQ, "Setting active threads list pointer.\n");
- activeThreads = at_ptr;
-}
-*/
-template <class Impl>
-void
-InstQueue<Impl>::setIssueToExecuteQueue(TimeBuffer<IssueStruct> *i2e_ptr)
-{
- DPRINTF(IQ, "Set the issue to execute queue.\n");
- issueToExecuteQueue = i2e_ptr;
-}
-/*
-template <class Impl>
-void
-InstQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
-{
- DPRINTF(IQ, "Set the time buffer.\n");
- timeBuffer = tb_ptr;
-
- fromCommit = timeBuffer->getWire(-commitToIEWDelay);
-}
-
-template <class Impl>
-int
-InstQueue<Impl>::entryAmount(int num_threads)
-{
- if (iqPolicy == Partitioned) {
- return numEntries / num_threads;
- } else {
- return 0;
- }
-}
-
-
-template <class Impl>
-void
-InstQueue<Impl>::resetEntries()
-{
- if (iqPolicy != Dynamic || numThreads > 1) {
- int active_threads = (*activeThreads).size();
-
- list<unsigned>::iterator threads = (*activeThreads).begin();
- list<unsigned>::iterator list_end = (*activeThreads).end();
-
- while (threads != list_end) {
- if (iqPolicy == Partitioned) {
- maxEntries[*threads++] = numEntries / active_threads;
- } else if(iqPolicy == Threshold && active_threads == 1) {
- maxEntries[*threads++] = numEntries;
- }
- }
- }
-}
-*/
-template <class Impl>
-unsigned
-InstQueue<Impl>::numFreeEntries()
-{
- return freeEntries;
-}
-
-template <class Impl>
-unsigned
-InstQueue<Impl>::numFreeEntries(unsigned tid)
-{
- return maxEntries[tid] - count[tid];
-}
-
-// Might want to do something more complex if it knows how many instructions
-// will be issued this cycle.
-template <class Impl>
-bool
-InstQueue<Impl>::isFull()
-{
- if (freeEntries == 0) {
- return(true);
- } else {
- return(false);
- }
-}
-
-template <class Impl>
-bool
-InstQueue<Impl>::isFull(unsigned tid)
-{
- if (numFreeEntries(tid) == 0) {
- return(true);
- } else {
- return(false);
- }
-}
-
-template <class Impl>
-bool
-InstQueue<Impl>::hasReadyInsts()
-{
-/*
- if (!listOrder.empty()) {
- return true;
- }
-
- for (int i = 0; i < Num_OpClasses; ++i) {
- if (!readyInsts[i].empty()) {
- return true;
- }
- }
-
- return false;
-*/
- return readyInsts.empty();
-}
-
-template <class Impl>
-void
-InstQueue<Impl>::insert(DynInstPtr &new_inst)
-{
- // Make sure the instruction is valid
- assert(new_inst);
-
- DPRINTF(IQ, "Adding instruction PC %#x to the IQ.\n",
- new_inst->readPC());
-
- // Check if there are any free entries. Panic if there are none.
- // Might want to have this return a fault in the future instead of
- // panicing.
- assert(freeEntries != 0);
-
- instList[new_inst->threadNumber].push_back(new_inst);
-
- // Decrease the number of free entries.
- --freeEntries;
-
- //Mark Instruction as in IQ
-// new_inst->setInIQ();
-/*
- // Look through its source registers (physical regs), and mark any
- // dependencies.
- addToDependents(new_inst);
-
- // Have this instruction set itself as the producer of its destination
- // register(s).
- createDependency(new_inst);
-*/
- // If it's a memory instruction, add it to the memory dependency
- // unit.
-// if (new_inst->isMemRef()) {
-// memDepUnit[new_inst->threadNumber].insert(new_inst);
-// } else {
- // If the instruction is ready then add it to the ready list.
- addIfReady(new_inst);
-// }
-
- ++iqInstsAdded;
-
-
- //Update Thread IQ Count
- count[new_inst->threadNumber]++;
-
- assert(freeEntries == (numEntries - countInsts()));
-}
-
-template <class Impl>
-void
-InstQueue<Impl>::insertNonSpec(DynInstPtr &new_inst)
-{
- nonSpecInsts[new_inst->seqNum] = new_inst;
-
- // @todo: Clean up this code; can do it by setting inst as unable
- // to issue, then calling normal insert on the inst.
-
- // Make sure the instruction is valid
- assert(new_inst);
-
- DPRINTF(IQ, "Adding instruction PC %#x to the IQ.\n",
- new_inst->readPC());
-
- // Check if there are any free entries. Panic if there are none.
- // Might want to have this return a fault in the future instead of
- // panicing.
- assert(freeEntries != 0);
-
- instList[new_inst->threadNumber].push_back(new_inst);
-
- // Decrease the number of free entries.
- --freeEntries;
-
- //Mark Instruction as in IQ
-// new_inst->setInIQ();
-/*
- // Have this instruction set itself as the producer of its destination
- // register(s).
- createDependency(new_inst);
-
- // If it's a memory instruction, add it to the memory dependency
- // unit.
- if (new_inst->isMemRef()) {
- memDepUnit[new_inst->threadNumber].insertNonSpec(new_inst);
- }
-*/
- ++iqNonSpecInstsAdded;
-
- //Update Thread IQ Count
- count[new_inst->threadNumber]++;
-
- assert(freeEntries == (numEntries - countInsts()));
-}
-/*
-template <class Impl>
-void
-InstQueue<Impl>::advanceTail(DynInstPtr &inst)
-{
- // Have this instruction set itself as the producer of its destination
- // register(s).
- createDependency(inst);
-}
-
-template <class Impl>
-void
-InstQueue<Impl>::addToOrderList(OpClass op_class)
-{
- assert(!readyInsts[op_class].empty());
-
- ListOrderEntry queue_entry;
-
- queue_entry.queueType = op_class;
-
- queue_entry.oldestInst = readyInsts[op_class].top()->seqNum;
-
- ListOrderIt list_it = listOrder.begin();
- ListOrderIt list_end_it = listOrder.end();
-
- while (list_it != list_end_it) {
- if ((*list_it).oldestInst > queue_entry.oldestInst) {
- break;
- }
-
- list_it++;
- }
-
- readyIt[op_class] = listOrder.insert(list_it, queue_entry);
- queueOnList[op_class] = true;
-}
-
-template <class Impl>
-void
-InstQueue<Impl>::moveToYoungerInst(ListOrderIt list_order_it)
-{
- // Get iterator of next item on the list
- // Delete the original iterator
- // Determine if the next item is either the end of the list or younger
- // than the new instruction. If so, then add in a new iterator right here.
- // If not, then move along.
- ListOrderEntry queue_entry;
- OpClass op_class = (*list_order_it).queueType;
- ListOrderIt next_it = list_order_it;
-
- ++next_it;
-
- queue_entry.queueType = op_class;
- queue_entry.oldestInst = readyInsts[op_class].top()->seqNum;
-
- while (next_it != listOrder.end() &&
- (*next_it).oldestInst < queue_entry.oldestInst) {
- ++next_it;
- }
-
- readyIt[op_class] = listOrder.insert(next_it, queue_entry);
-}
-
-template <class Impl>
-void
-InstQueue<Impl>::processFUCompletion(DynInstPtr &inst, int fu_idx)
-{
- // The CPU could have been sleeping until this op completed (*extremely*
- // long latency op). Wake it if it was. This may be overkill.
- iewStage->wakeCPU();
-
- fuPool->freeUnit(fu_idx);
-
- int &size = issueToExecuteQueue->access(0)->size;
-
- issueToExecuteQueue->access(0)->insts[size++] = inst;
-}
-*/
-// @todo: Figure out a better way to remove the squashed items from the
-// lists. Checking the top item of each list to see if it's squashed
-// wastes time and forces jumps.
-template <class Impl>
-void
-InstQueue<Impl>::scheduleReadyInsts()
-{
- DPRINTF(IQ, "Attempting to schedule ready instructions from "
- "the IQ.\n");
-
-// IssueStruct *i2e_info = issueToExecuteQueue->access(0);
-/*
- // Will need to reorder the list if either a queue is not on the list,
- // or it has an older instruction than last time.
- for (int i = 0; i < Num_OpClasses; ++i) {
- if (!readyInsts[i].empty()) {
- if (!queueOnList[i]) {
- addToOrderList(OpClass(i));
- } else if (readyInsts[i].top()->seqNum <
- (*readyIt[i]).oldestInst) {
- listOrder.erase(readyIt[i]);
- addToOrderList(OpClass(i));
- }
- }
- }
-
- // Have iterator to head of the list
- // While I haven't exceeded bandwidth or reached the end of the list,
- // Try to get a FU that can do what this op needs.
- // If successful, change the oldestInst to the new top of the list, put
- // the queue in the proper place in the list.
- // Increment the iterator.
- // This will avoid trying to schedule a certain op class if there are no
- // FUs that handle it.
- ListOrderIt order_it = listOrder.begin();
- ListOrderIt order_end_it = listOrder.end();
- int total_issued = 0;
- int exec_queue_slot = i2e_info->size;
-
- while (exec_queue_slot < totalWidth && order_it != order_end_it) {
- OpClass op_class = (*order_it).queueType;
-
- assert(!readyInsts[op_class].empty());
-
- DynInstPtr issuing_inst = readyInsts[op_class].top();
-
- assert(issuing_inst->seqNum == (*order_it).oldestInst);
-
- if (issuing_inst->isSquashed()) {
- readyInsts[op_class].pop();
-
- if (!readyInsts[op_class].empty()) {
- moveToYoungerInst(order_it);
- } else {
- readyIt[op_class] = listOrder.end();
- queueOnList[op_class] = false;
- }
-
- listOrder.erase(order_it++);
-
- ++iqSquashedInstsIssued;
-
- continue;
- }
-
- int idx = fuPool->getUnit(op_class);
-
- if (idx != -1) {
- int op_latency = fuPool->getOpLatency(op_class);
-
- if (op_latency == 1) {
- i2e_info->insts[exec_queue_slot++] = issuing_inst;
- i2e_info->size++;
-
- // Add the FU onto the list of FU's to be freed next cycle.
- fuPool->freeUnit(idx);
- } else {
- int issue_latency = fuPool->getIssueLatency(op_class);
-
- if (issue_latency > 1) {
- // Generate completion event for the FU
- FUCompletion *execution = new FUCompletion(issuing_inst,
- idx, this);
-
- execution->schedule(curTick + issue_latency - 1);
- } else {
- i2e_info->insts[exec_queue_slot++] = issuing_inst;
- i2e_info->size++;
-
- // Add the FU onto the list of FU's to be freed next cycle.
- fuPool->freeUnit(idx);
- }
- }
-
- DPRINTF(IQ, "Thread %i: Issuing instruction PC %#x "
- "[sn:%lli]\n",
- issuing_inst->threadNumber, issuing_inst->readPC(),
- issuing_inst->seqNum);
-
- readyInsts[op_class].pop();
-
- if (!readyInsts[op_class].empty()) {
- moveToYoungerInst(order_it);
- } else {
- readyIt[op_class] = listOrder.end();
- queueOnList[op_class] = false;
- }
-
- issuing_inst->setIssued();
- ++total_issued;
-
- if (!issuing_inst->isMemRef()) {
- // Memory instructions can not be freed from the IQ until they
- // complete.
- ++freeEntries;
- count[issuing_inst->threadNumber]--;
- issuing_inst->removeInIQ();
- } else {
- memDepUnit[issuing_inst->threadNumber].issue(issuing_inst);
- }
-
- listOrder.erase(order_it++);
- } else {
- ++order_it;
- }
- }
-
- if (total_issued) {
- cpu->activityThisCycle();
- } else {
- DPRINTF(IQ, "Not able to schedule any instructions.\n");
- }
-*/
-}
-
-template <class Impl>
-void
-InstQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst)
-{
- DPRINTF(IQ, "Marking nonspeculative instruction with sequence "
- "number %i as ready to execute.\n", inst);
-
- NonSpecMapIt inst_it = nonSpecInsts.find(inst);
-
- assert(inst_it != nonSpecInsts.end());
-
-// unsigned tid = (*inst_it).second->threadNumber;
-
- // Mark this instruction as ready to issue.
- (*inst_it).second->setCanIssue();
-
- // Now schedule the instruction.
-// if (!(*inst_it).second->isMemRef()) {
- addIfReady((*inst_it).second);
-// } else {
-// memDepUnit[tid].nonSpecInstReady((*inst_it).second);
-// }
-
- nonSpecInsts.erase(inst_it);
-}
-
-template <class Impl>
-void
-InstQueue<Impl>::commit(const InstSeqNum &inst, unsigned tid)
-{
- /*Need to go through each thread??*/
- DPRINTF(IQ, "[tid:%i]: Committing instructions older than [sn:%i]\n",
- tid,inst);
-
- ListIt iq_it = instList[tid].begin();
-
- while (iq_it != instList[tid].end() &&
- (*iq_it)->seqNum <= inst) {
- ++iq_it;
- instList[tid].pop_front();
- }
-
- assert(freeEntries == (numEntries - countInsts()));
-}
-
-template <class Impl>
-void
-InstQueue<Impl>::wakeDependents(DynInstPtr &completed_inst)
-{
- DPRINTF(IQ, "Waking dependents of completed instruction.\n");
- // Look at the physical destination register of the DynInst
- // and look it up on the dependency graph. Then mark as ready
- // any instructions within the instruction queue.
-/*
- DependencyEntry *curr;
- DependencyEntry *prev;
-*/
- // Tell the memory dependence unit to wake any dependents on this
- // instruction if it is a memory instruction. Also complete the memory
- // instruction at this point since we know it executed fine.
- // @todo: Might want to rename "completeMemInst" to
- // something that indicates that it won't need to be replayed, and call
- // this earlier. Might not be a big deal.
- if (completed_inst->isMemRef()) {
-// memDepUnit[completed_inst->threadNumber].wakeDependents(completed_inst);
- completeMemInst(completed_inst);
- }
- completed_inst->wakeDependents();
-/*
- for (int dest_reg_idx = 0;
- dest_reg_idx < completed_inst->numDestRegs();
- dest_reg_idx++)
- {
- PhysRegIndex dest_reg =
- completed_inst->renamedDestRegIdx(dest_reg_idx);
-
- // Special case of uniq or control registers. They are not
- // handled by the IQ and thus have no dependency graph entry.
- // @todo Figure out a cleaner way to handle this.
- if (dest_reg >= numPhysRegs) {
- continue;
- }
-
- DPRINTF(IQ, "Waking any dependents on register %i.\n",
- (int) dest_reg);
-
- //Maybe abstract this part into a function.
- //Go through the dependency chain, marking the registers as ready
- //within the waiting instructions.
-
- curr = dependGraph[dest_reg].next;
-
- while (curr) {
- DPRINTF(IQ, "Waking up a dependent instruction, PC%#x.\n",
- curr->inst->readPC());
-
- // Might want to give more information to the instruction
- // so that it knows which of its source registers is ready.
- // However that would mean that the dependency graph entries
- // would need to hold the src_reg_idx.
- curr->inst->markSrcRegReady();
-
- addIfReady(curr->inst);
-
- DependencyEntry::mem_alloc_counter--;
-
- prev = curr;
- curr = prev->next;
- prev->inst = NULL;
-
- delete prev;
- }
-
- // Reset the head node now that all of its dependents have been woken
- // up.
- dependGraph[dest_reg].next = NULL;
- dependGraph[dest_reg].inst = NULL;
-
- // Mark the scoreboard as having that register ready.
- regScoreboard[dest_reg] = true;
- }
-*/
-}
-
-template <class Impl>
-void
-InstQueue<Impl>::addReadyMemInst(DynInstPtr &ready_inst)
-{
- OpClass op_class = ready_inst->opClass();
-
- readyInsts.push(ready_inst);
-
- DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
- "the ready list, PC %#x opclass:%i [sn:%lli].\n",
- ready_inst->readPC(), op_class, ready_inst->seqNum);
-}
-/*
-template <class Impl>
-void
-InstQueue<Impl>::rescheduleMemInst(DynInstPtr &resched_inst)
-{
- memDepUnit[resched_inst->threadNumber].reschedule(resched_inst);
-}
-
-template <class Impl>
-void
-InstQueue<Impl>::replayMemInst(DynInstPtr &replay_inst)
-{
- memDepUnit[replay_inst->threadNumber].replay(replay_inst);
-}
-*/
-template <class Impl>
-void
-InstQueue<Impl>::completeMemInst(DynInstPtr &completed_inst)
-{
- int tid = completed_inst->threadNumber;
-
- DPRINTF(IQ, "Completing mem instruction PC:%#x [sn:%lli]\n",
- completed_inst->readPC(), completed_inst->seqNum);
-
- ++freeEntries;
-
-// completed_inst->memOpDone = true;
-
-// memDepUnit[tid].completed(completed_inst);
-
- count[tid]--;
-}
-/*
-template <class Impl>
-void
-InstQueue<Impl>::violation(DynInstPtr &store,
- DynInstPtr &faulting_load)
-{
- memDepUnit[store->threadNumber].violation(store, faulting_load);
-}
-*/
-template <class Impl>
-void
-InstQueue<Impl>::squash(unsigned tid)
-{
- DPRINTF(IQ, "[tid:%i]: Starting to squash instructions in "
- "the IQ.\n", tid);
-
- // Read instruction sequence number of last instruction out of the
- // time buffer.
-// squashedSeqNum[tid] = fromCommit->commitInfo[tid].doneSeqNum;
-
- // Setup the squash iterator to point to the tail.
- squashIt[tid] = instList[tid].end();
- --squashIt[tid];
-
- // Call doSquash if there are insts in the IQ
- if (count[tid] > 0) {
- doSquash(tid);
- }
-
- // Also tell the memory dependence unit to squash.
-// memDepUnit[tid].squash(squashedSeqNum[tid], tid);
-}
-
-template <class Impl>
-void
-InstQueue<Impl>::doSquash(unsigned tid)
-{
- // Make sure the squashed sequence number is valid.
- assert(squashedSeqNum[tid] != 0);
-
- DPRINTF(IQ, "[tid:%i]: Squashing until sequence number %i!\n",
- tid, squashedSeqNum[tid]);
-
- // Squash any instructions younger than the squashed sequence number
- // given.
- while (squashIt[tid] != instList[tid].end() &&
- (*squashIt[tid])->seqNum > squashedSeqNum[tid]) {
-
- DynInstPtr squashed_inst = (*squashIt[tid]);
-
- // Only handle the instruction if it actually is in the IQ and
- // hasn't already been squashed in the IQ.
- if (squashed_inst->threadNumber != tid ||
- squashed_inst->isSquashedInIQ()) {
- --squashIt[tid];
- continue;
- }
-
- if (!squashed_inst->isIssued() ||
- (squashed_inst->isMemRef()/* &&
- !squashed_inst->memOpDone*/)) {
-
- // Remove the instruction from the dependency list.
- if (!squashed_inst->isNonSpeculative()) {
-/*
- for (int src_reg_idx = 0;
- src_reg_idx < squashed_inst->numSrcRegs();
- src_reg_idx++)
- {
- PhysRegIndex src_reg =
- squashed_inst->renamedSrcRegIdx(src_reg_idx);
-
- // Only remove it from the dependency graph if it was
- // placed there in the first place.
- // HACK: This assumes that instructions woken up from the
- // dependency chain aren't informed that a specific src
- // register has become ready. This may not always be true
- // in the future.
- // Instead of doing a linked list traversal, we can just
- // remove these squashed instructions either at issue time,
- // or when the register is overwritten. The only downside
- // to this is it leaves more room for error.
-
- if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) &&
- src_reg < numPhysRegs) {
- dependGraph[src_reg].remove(squashed_inst);
- }
-
-
- ++iqSquashedOperandsExamined;
- }
-*/
- // Might want to remove producers as well.
- } else {
- nonSpecInsts[squashed_inst->seqNum] = NULL;
-
- nonSpecInsts.erase(squashed_inst->seqNum);
-
- ++iqSquashedNonSpecRemoved;
- }
-
- // Might want to also clear out the head of the dependency graph.
-
- // Mark it as squashed within the IQ.
- squashed_inst->setSquashedInIQ();
-
- // @todo: Remove this hack where several statuses are set so the
- // inst will flow through the rest of the pipeline.
- squashed_inst->setIssued();
- squashed_inst->setCanCommit();
-// squashed_inst->removeInIQ();
-
- //Update Thread IQ Count
- count[squashed_inst->threadNumber]--;
-
- ++freeEntries;
-
- if (numThreads > 1) {
- DPRINTF(IQ, "[tid:%i]: Instruction PC %#x squashed.\n",
- tid, squashed_inst->readPC());
- } else {
- DPRINTF(IQ, "Instruction PC %#x squashed.\n",
- squashed_inst->readPC());
- }
- }
-
- --squashIt[tid];
- ++iqSquashedInstsExamined;
- }
-}
-/*
-template <class Impl>
-void
-InstQueue<Impl>::DependencyEntry::insert(DynInstPtr &new_inst)
-{
- //Add this new, dependent instruction at the head of the dependency
- //chain.
-
- // First create the entry that will be added to the head of the
- // dependency chain.
- DependencyEntry *new_entry = new DependencyEntry;
- new_entry->next = this->next;
- new_entry->inst = new_inst;
-
- // Then actually add it to the chain.
- this->next = new_entry;
-
- ++mem_alloc_counter;
-}
-
-template <class Impl>
-void
-InstQueue<Impl>::DependencyEntry::remove(DynInstPtr &inst_to_remove)
-{
- DependencyEntry *prev = this;
- DependencyEntry *curr = this->next;
-
- // Make sure curr isn't NULL. Because this instruction is being
- // removed from a dependency list, it must have been placed there at
- // an earlier time. The dependency chain should not be empty,
- // unless the instruction dependent upon it is already ready.
- if (curr == NULL) {
- return;
- }
-
- // Find the instruction to remove within the dependency linked list.
- while (curr->inst != inst_to_remove) {
- prev = curr;
- curr = curr->next;
-
- assert(curr != NULL);
- }
-
- // Now remove this instruction from the list.
- prev->next = curr->next;
-
- --mem_alloc_counter;
-
- // Could push this off to the destructor of DependencyEntry
- curr->inst = NULL;
-
- delete curr;
-}
-
-template <class Impl>
-bool
-InstQueue<Impl>::addToDependents(DynInstPtr &new_inst)
-{
- // Loop through the instruction's source registers, adding
- // them to the dependency list if they are not ready.
- int8_t total_src_regs = new_inst->numSrcRegs();
- bool return_val = false;
-
- for (int src_reg_idx = 0;
- src_reg_idx < total_src_regs;
- src_reg_idx++)
- {
- // Only add it to the dependency graph if it's not ready.
- if (!new_inst->isReadySrcRegIdx(src_reg_idx)) {
- PhysRegIndex src_reg = new_inst->renamedSrcRegIdx(src_reg_idx);
-
- // Check the IQ's scoreboard to make sure the register
- // hasn't become ready while the instruction was in flight
- // between stages. Only if it really isn't ready should
- // it be added to the dependency graph.
- if (src_reg >= numPhysRegs) {
- continue;
- } else if (regScoreboard[src_reg] == false) {
- DPRINTF(IQ, "Instruction PC %#x has src reg %i that "
- "is being added to the dependency chain.\n",
- new_inst->readPC(), src_reg);
-
- dependGraph[src_reg].insert(new_inst);
-
- // Change the return value to indicate that something
- // was added to the dependency graph.
- return_val = true;
- } else {
- DPRINTF(IQ, "Instruction PC %#x has src reg %i that "
- "became ready before it reached the IQ.\n",
- new_inst->readPC(), src_reg);
- // Mark a register ready within the instruction.
- new_inst->markSrcRegReady();
- }
- }
- }
-
- return return_val;
-}
-
-template <class Impl>
-void
-InstQueue<Impl>::createDependency(DynInstPtr &new_inst)
-{
- //Actually nothing really needs to be marked when an
- //instruction becomes the producer of a register's value,
- //but for convenience a ptr to the producing instruction will
- //be placed in the head node of the dependency links.
- int8_t total_dest_regs = new_inst->numDestRegs();
-
- for (int dest_reg_idx = 0;
- dest_reg_idx < total_dest_regs;
- dest_reg_idx++)
- {
- PhysRegIndex dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx);
-
- // Instructions that use the misc regs will have a reg number
- // higher than the normal physical registers. In this case these
- // registers are not renamed, and there is no need to track
- // dependencies as these instructions must be executed at commit.
- if (dest_reg >= numPhysRegs) {
- continue;
- }
-
- if (dependGraph[dest_reg].next) {
- dumpDependGraph();
- panic("Dependency graph %i not empty!", dest_reg);
- }
-
- dependGraph[dest_reg].inst = new_inst;
-
- // Mark the scoreboard to say it's not yet ready.
- regScoreboard[dest_reg] = false;
- }
-}
-*/
-template <class Impl>
-void
-InstQueue<Impl>::addIfReady(DynInstPtr &inst)
-{
- //If the instruction now has all of its source registers
- // available, then add it to the list of ready instructions.
- if (inst->readyToIssue()) {
-
- //Add the instruction to the proper ready list.
- if (inst->isMemRef()) {
-
- DPRINTF(IQ, "Checking if memory instruction can issue.\n");
-
- // Message to the mem dependence unit that this instruction has
- // its registers ready.
-
-// memDepUnit[inst->threadNumber].regsReady(inst);
-
- return;
- }
-
- OpClass op_class = inst->opClass();
-
- DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
- "the ready list, PC %#x opclass:%i [sn:%lli].\n",
- inst->readPC(), op_class, inst->seqNum);
-
- readyInsts.push(inst);
- }
-}
-
-template <class Impl>
-int
-InstQueue<Impl>::countInsts()
-{
- //ksewell:This works but definitely could use a cleaner write
- //with a more intuitive way of counting. Right now it's
- //just brute force ....
-
-#if 0
- int total_insts = 0;
-
- for (int i = 0; i < numThreads; ++i) {
- ListIt count_it = instList[i].begin();
-
- while (count_it != instList[i].end()) {
- if (!(*count_it)->isSquashed() && !(*count_it)->isSquashedInIQ()) {
- if (!(*count_it)->isIssued()) {
- ++total_insts;
- } else if ((*count_it)->isMemRef() &&
- !(*count_it)->memOpDone) {
- // Loads that have not been marked as executed still count
- // towards the total instructions.
- ++total_insts;
- }
- }
-
- ++count_it;
- }
- }
-
- return total_insts;
-#else
- return numEntries - freeEntries;
-#endif
-}
-/*
-template <class Impl>
-void
-InstQueue<Impl>::dumpDependGraph()
-{
- DependencyEntry *curr;
-
- for (int i = 0; i < numPhysRegs; ++i)
- {
- curr = &dependGraph[i];
-
- if (curr->inst) {
- cprintf("dependGraph[%i]: producer: %#x [sn:%lli] consumer: ",
- i, curr->inst->readPC(), curr->inst->seqNum);
- } else {
- cprintf("dependGraph[%i]: No producer. consumer: ", i);
- }
-
- while (curr->next != NULL) {
- curr = curr->next;
-
- cprintf("%#x [sn:%lli] ",
- curr->inst->readPC(), curr->inst->seqNum);
- }
-
- cprintf("\n");
- }
-}
-*/
-template <class Impl>
-void
-InstQueue<Impl>::dumpLists()
-{
- for (int i = 0; i < Num_OpClasses; ++i) {
- cprintf("Ready list %i size: %i\n", i, readyInsts.size());
-
- cprintf("\n");
- }
-
- cprintf("Non speculative list size: %i\n", nonSpecInsts.size());
-
- NonSpecMapIt non_spec_it = nonSpecInsts.begin();
- NonSpecMapIt non_spec_end_it = nonSpecInsts.end();
-
- cprintf("Non speculative list: ");
-
- while (non_spec_it != non_spec_end_it) {
- cprintf("%#x [sn:%lli]", (*non_spec_it).second->readPC(),
- (*non_spec_it).second->seqNum);
- ++non_spec_it;
- }
-
- cprintf("\n");
-/*
- ListOrderIt list_order_it = listOrder.begin();
- ListOrderIt list_order_end_it = listOrder.end();
- int i = 1;
-
- cprintf("List order: ");
-
- while (list_order_it != list_order_end_it) {
- cprintf("%i OpClass:%i [sn:%lli] ", i, (*list_order_it).queueType,
- (*list_order_it).oldestInst);
-
- ++list_order_it;
- ++i;
- }
-*/
- cprintf("\n");
-}
-
-
-template <class Impl>
-void
-InstQueue<Impl>::dumpInsts()
-{
- for (int i = 0; i < numThreads; ++i) {
-// int num = 0;
-// int valid_num = 0;
-/*
- ListIt inst_list_it = instList[i].begin();
-
- while (inst_list_it != instList[i].end())
- {
- cprintf("Instruction:%i\n",
- num);
- if (!(*inst_list_it)->isSquashed()) {
- if (!(*inst_list_it)->isIssued()) {
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- } else if ((*inst_list_it)->isMemRef() &&
- !(*inst_list_it)->memOpDone) {
- // Loads that have not been marked as executed still count
- // towards the total instructions.
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- }
- }
-
- cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
- "Issued:%i\nSquashed:%i\n",
- (*inst_list_it)->readPC(),
- (*inst_list_it)->seqNum,
- (*inst_list_it)->threadNumber,
- (*inst_list_it)->isIssued(),
- (*inst_list_it)->isSquashed());
-
- if ((*inst_list_it)->isMemRef()) {
- cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
- }
-
- cprintf("\n");
-
- inst_list_it++;
- ++num;
- }
-*/
- }
-}
diff --git a/cpu/ozone/lsq_unit.cc b/cpu/ozone/lsq_unit.cc
deleted file mode 100644
index 3ac51b87d..000000000
--- a/cpu/ozone/lsq_unit.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/ozone/ozone_impl.hh"
-#include "cpu/ozone/lsq_unit_impl.hh"
-
-// Force the instantiation of LDSTQ for all the implementations we care about.
-template class OzoneLSQ<OzoneImpl>;
-
diff --git a/cpu/ozone/lsq_unit.hh b/cpu/ozone/lsq_unit.hh
deleted file mode 100644
index 4b600af67..000000000
--- a/cpu/ozone/lsq_unit.hh
+++ /dev/null
@@ -1,637 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_OZONE_LSQ_UNIT_HH__
-#define __CPU_OZONE_LSQ_UNIT_HH__
-
-#include <map>
-#include <queue>
-#include <algorithm>
-
-#include "arch/faults.hh"
-#include "arch/isa_traits.hh"
-#include "config/full_system.hh"
-#include "base/hashmap.hh"
-#include "cpu/inst_seq.hh"
-#include "mem/mem_interface.hh"
-//#include "mem/page_table.hh"
-#include "sim/sim_object.hh"
-
-class PageTable;
-
-/**
- * Class that implements the actual LQ and SQ for each specific thread.
- * Both are circular queues; load entries are freed upon committing, while
- * store entries are freed once they writeback. The LSQUnit tracks if there
- * are memory ordering violations, and also detects partial load to store
- * forwarding cases (a store only has part of a load's data) that requires
- * the load to wait until the store writes back. In the former case it
- * holds onto the instruction until the dependence unit looks at it, and
- * in the latter it stalls the LSQ until the store writes back. At that
- * point the load is replayed.
- */
-template <class Impl>
-class OzoneLSQ {
- public:
- typedef typename Impl::Params Params;
- typedef typename Impl::FullCPU FullCPU;
- typedef typename Impl::BackEnd BackEnd;
- typedef typename Impl::DynInstPtr DynInstPtr;
- typedef typename Impl::IssueStruct IssueStruct;
-
- typedef TheISA::IntReg IntReg;
-
- typedef typename std::map<InstSeqNum, DynInstPtr>::iterator LdMapIt;
-
- private:
- class StoreCompletionEvent : public Event {
- public:
- /** Constructs a store completion event. */
- StoreCompletionEvent(int store_idx, Event *wb_event, OzoneLSQ *lsq_ptr);
-
- /** Processes the store completion event. */
- void process();
-
- /** Returns the description of this event. */
- const char *description();
-
- private:
- /** The store index of the store being written back. */
- int storeIdx;
- /** The writeback event for the store. Needed for store
- * conditionals.
- */
- Event *wbEvent;
- /** The pointer to the LSQ unit that issued the store. */
- OzoneLSQ<Impl> *lsqPtr;
- };
-
- friend class StoreCompletionEvent;
-
- public:
- /** Constructs an LSQ unit. init() must be called prior to use. */
- OzoneLSQ();
-
- /** Initializes the LSQ unit with the specified number of entries. */
- void init(Params *params, unsigned maxLQEntries,
- unsigned maxSQEntries, unsigned id);
-
- /** Returns the name of the LSQ unit. */
- std::string name() const;
-
- /** Sets the CPU pointer. */
- void setCPU(FullCPU *cpu_ptr)
- { cpu = cpu_ptr; }
-
- /** Sets the back-end stage pointer. */
- void setBE(BackEnd *be_ptr)
- { be = be_ptr; }
-
- /** Sets the page table pointer. */
- void setPageTable(PageTable *pt_ptr);
-
- /** Ticks the LSQ unit, which in this case only resets the number of
- * used cache ports.
- * @todo: Move the number of used ports up to the LSQ level so it can
- * be shared by all LSQ units.
- */
- void tick() { usedPorts = 0; }
-
- /** Inserts an instruction. */
- void insert(DynInstPtr &inst);
- /** Inserts a load instruction. */
- void insertLoad(DynInstPtr &load_inst);
- /** Inserts a store instruction. */
- void insertStore(DynInstPtr &store_inst);
-
- /** Executes a load instruction. */
- Fault executeLoad(DynInstPtr &inst);
-
- Fault executeLoad(int lq_idx);
- /** Executes a store instruction. */
- Fault executeStore(DynInstPtr &inst);
-
- /** Commits the head load. */
- void commitLoad();
- /** Commits a specific load, given by the sequence number. */
- void commitLoad(InstSeqNum &inst);
- /** Commits loads older than a specific sequence number. */
- void commitLoads(InstSeqNum &youngest_inst);
-
- /** Commits stores older than a specific sequence number. */
- void commitStores(InstSeqNum &youngest_inst);
-
- /** Writes back stores. */
- void writebackStores();
-
- // @todo: Include stats in the LSQ unit.
- //void regStats();
-
- /** Clears all the entries in the LQ. */
- void clearLQ();
-
- /** Clears all the entries in the SQ. */
- void clearSQ();
-
- /** Resizes the LQ to a given size. */
- void resizeLQ(unsigned size);
-
- /** Resizes the SQ to a given size. */
- void resizeSQ(unsigned size);
-
- /** Squashes all instructions younger than a specific sequence number. */
- void squash(const InstSeqNum &squashed_num);
-
- /** Returns if there is a memory ordering violation. Value is reset upon
- * call to getMemDepViolator().
- */
- bool violation() { return memDepViolator; }
-
- /** Returns the memory ordering violator. */
- DynInstPtr getMemDepViolator();
-
- /** Returns if a load became blocked due to the memory system. It clears
- * the bool's value upon this being called.
- */
- inline bool loadBlocked();
-
- /** Returns the number of free entries (min of free LQ and SQ entries). */
- unsigned numFreeEntries();
-
- /** Returns the number of loads ready to execute. */
- int numLoadsReady();
-
- /** Returns the number of loads in the LQ. */
- int numLoads() { return loads; }
-
- /** Returns the number of stores in the SQ. */
- int numStores() { return stores; }
-
- /** Returns if either the LQ or SQ is full. */
- bool isFull() { return lqFull() || sqFull(); }
-
- /** Returns if the LQ is full. */
- bool lqFull() { return loads >= (LQEntries - 1); }
-
- /** Returns if the SQ is full. */
- bool sqFull() { return stores >= (SQEntries - 1); }
-
- /** Debugging function to dump instructions in the LSQ. */
- void dumpInsts();
-
- /** Returns the number of instructions in the LSQ. */
- unsigned getCount() { return loads + stores; }
-
- /** Returns if there are any stores to writeback. */
- bool hasStoresToWB() { return storesToWB; }
-
- /** Returns the number of stores to writeback. */
- int numStoresToWB() { return storesToWB; }
-
- /** Returns if the LSQ unit will writeback on this cycle. */
- bool willWB() { return storeQueue[storeWBIdx].canWB &&
- !storeQueue[storeWBIdx].completed &&
- !dcacheInterface->isBlocked(); }
-
- private:
- /** Completes the store at the specified index. */
- void completeStore(int store_idx);
-
- /** Increments the given store index (circular queue). */
- inline void incrStIdx(int &store_idx);
- /** Decrements the given store index (circular queue). */
- inline void decrStIdx(int &store_idx);
- /** Increments the given load index (circular queue). */
- inline void incrLdIdx(int &load_idx);
- /** Decrements the given load index (circular queue). */
- inline void decrLdIdx(int &load_idx);
-
- private:
- /** Pointer to the CPU. */
- FullCPU *cpu;
-
- /** Pointer to the back-end stage. */
- BackEnd *be;
-
- /** Pointer to the D-cache. */
- MemInterface *dcacheInterface;
-
- /** Pointer to the page table. */
- PageTable *pTable;
-
- public:
- struct SQEntry {
- /** Constructs an empty store queue entry. */
- SQEntry()
- : inst(NULL), req(NULL), size(0), data(0),
- canWB(0), committed(0), completed(0)
- { }
-
- /** Constructs a store queue entry for a given instruction. */
- SQEntry(DynInstPtr &_inst)
- : inst(_inst), req(NULL), size(0), data(0),
- canWB(0), committed(0), completed(0)
- { }
-
- /** The store instruction. */
- DynInstPtr inst;
- /** The memory request for the store. */
- MemReqPtr req;
- /** The size of the store. */
- int size;
- /** The store data. */
- IntReg data;
- /** Whether or not the store can writeback. */
- bool canWB;
- /** Whether or not the store is committed. */
- bool committed;
- /** Whether or not the store is completed. */
- bool completed;
- };
-
- enum Status {
- Running,
- Idle,
- DcacheMissStall,
- DcacheMissSwitch
- };
-
- private:
- /** The OzoneLSQ thread id. */
- unsigned lsqID;
-
- /** The status of the LSQ unit. */
- Status _status;
-
- /** The store queue. */
- std::vector<SQEntry> storeQueue;
-
- /** The load queue. */
- std::vector<DynInstPtr> loadQueue;
-
- // Consider making these 16 bits
- /** The number of LQ entries. */
- unsigned LQEntries;
- /** The number of SQ entries. */
- unsigned SQEntries;
-
- /** The number of load instructions in the LQ. */
- int loads;
- /** The number of store instructions in the SQ (excludes those waiting to
- * writeback).
- */
- int stores;
- /** The number of store instructions in the SQ waiting to writeback. */
- int storesToWB;
-
- /** The index of the head instruction in the LQ. */
- int loadHead;
- /** The index of the tail instruction in the LQ. */
- int loadTail;
-
- /** The index of the head instruction in the SQ. */
- int storeHead;
- /** The index of the first instruction that is ready to be written back,
- * and has not yet been written back.
- */
- int storeWBIdx;
- /** The index of the tail instruction in the SQ. */
- int storeTail;
-
- /// @todo Consider moving to a more advanced model with write vs read ports
- /** The number of cache ports available each cycle. */
- int cachePorts;
-
- /** The number of used cache ports in this cycle. */
- int usedPorts;
-
- //list<InstSeqNum> mshrSeqNums;
-
- //Stats::Scalar<> dcacheStallCycles;
- Counter lastDcacheStall;
-
- /** Wire to read information from the issue stage time queue. */
- typename TimeBuffer<IssueStruct>::wire fromIssue;
-
- // Make these per thread?
- /** Whether or not the LSQ is stalled. */
- bool stalled;
- /** The store that causes the stall due to partial store to load
- * forwarding.
- */
- InstSeqNum stallingStoreIsn;
- /** The index of the above store. */
- int stallingLoadIdx;
-
- /** Whether or not a load is blocked due to the memory system. It is
- * cleared when this value is checked via loadBlocked().
- */
- bool isLoadBlocked;
-
- /** The oldest faulting load instruction. */
- DynInstPtr loadFaultInst;
- /** The oldest faulting store instruction. */
- DynInstPtr storeFaultInst;
-
- /** The oldest load that caused a memory ordering violation. */
- DynInstPtr memDepViolator;
-
- // Will also need how many read/write ports the Dcache has. Or keep track
- // of that in stage that is one level up, and only call executeLoad/Store
- // the appropriate number of times.
-
- public:
- /** Executes the load at the given index. */
- template <class T>
- Fault read(MemReqPtr &req, T &data, int load_idx);
-
- /** Executes the store at the given index. */
- template <class T>
- Fault write(MemReqPtr &req, T &data, int store_idx);
-
- /** Returns the index of the head load instruction. */
- int getLoadHead() { return loadHead; }
- /** Returns the sequence number of the head load instruction. */
- InstSeqNum getLoadHeadSeqNum()
- {
- if (loadQueue[loadHead]) {
- return loadQueue[loadHead]->seqNum;
- } else {
- return 0;
- }
-
- }
-
- /** Returns the index of the head store instruction. */
- int getStoreHead() { return storeHead; }
- /** Returns the sequence number of the head store instruction. */
- InstSeqNum getStoreHeadSeqNum()
- {
- if (storeQueue[storeHead].inst) {
- return storeQueue[storeHead].inst->seqNum;
- } else {
- return 0;
- }
-
- }
-
- /** Returns whether or not the LSQ unit is stalled. */
- bool isStalled() { return stalled; }
-};
-
-template <class Impl>
-template <class T>
-Fault
-OzoneLSQ<Impl>::read(MemReqPtr &req, T &data, int load_idx)
-{
- //Depending on issue2execute delay a squashed load could
- //execute if it is found to be squashed in the same
- //cycle it is scheduled to execute
- assert(loadQueue[load_idx]);
-
- if (loadQueue[load_idx]->isExecuted()) {
- panic("Should not reach this point with split ops!");
-
- memcpy(&data,req->data,req->size);
-
- return NoFault;
- }
-
- // Make sure this isn't an uncacheable access
- // A bit of a hackish way to get uncached accesses to work only if they're
- // at the head of the LSQ and are ready to commit (at the head of the ROB
- // too).
- // @todo: Fix uncached accesses.
- if (req->flags & UNCACHEABLE &&
- (load_idx != loadHead || !loadQueue[load_idx]->readyToCommit())) {
-
- return TheISA::genMachineCheckFault();
- }
-
- // Check the SQ for any previous stores that might lead to forwarding
- int store_idx = loadQueue[load_idx]->sqIdx;
-
- int store_size = 0;
-
- DPRINTF(OzoneLSQ, "Read called, load idx: %i, store idx: %i, "
- "storeHead: %i addr: %#x\n",
- load_idx, store_idx, storeHead, req->paddr);
-
- while (store_idx != -1) {
- // End once we've reached the top of the LSQ
- if (store_idx == storeWBIdx) {
- break;
- }
-
- // Move the index to one younger
- if (--store_idx < 0)
- store_idx += SQEntries;
-
- assert(storeQueue[store_idx].inst);
-
- store_size = storeQueue[store_idx].size;
-
- if (store_size == 0)
- continue;
-
- // Check if the store data is within the lower and upper bounds of
- // addresses that the request needs.
- bool store_has_lower_limit =
- req->vaddr >= storeQueue[store_idx].inst->effAddr;
- bool store_has_upper_limit =
- (req->vaddr + req->size) <= (storeQueue[store_idx].inst->effAddr +
- store_size);
- bool lower_load_has_store_part =
- req->vaddr < (storeQueue[store_idx].inst->effAddr +
- store_size);
- bool upper_load_has_store_part =
- (req->vaddr + req->size) > storeQueue[store_idx].inst->effAddr;
-
- // If the store's data has all of the data needed, we can forward.
- if (store_has_lower_limit && store_has_upper_limit) {
-
- int shift_amt = req->vaddr & (store_size - 1);
- // Assumes byte addressing
- shift_amt = shift_amt << 3;
-
- // Cast this to type T?
- data = storeQueue[store_idx].data >> shift_amt;
-
- req->cmd = Read;
- assert(!req->completionEvent);
- req->completionEvent = NULL;
- req->time = curTick;
- assert(!req->data);
- req->data = new uint8_t[64];
-
- memcpy(req->data, &data, req->size);
-
- DPRINTF(OzoneLSQ, "Forwarding from store idx %i to load to "
- "addr %#x, data %#x\n",
- store_idx, req->vaddr, *(req->data));
-
- typename BackEnd::LdWritebackEvent *wb =
- new typename BackEnd::LdWritebackEvent(loadQueue[load_idx],
- be);
-
- // We'll say this has a 1 cycle load-store forwarding latency
- // for now.
- // FIXME - Need to make this a parameter.
- wb->schedule(curTick);
-
- // Should keep track of stat for forwarded data
- return NoFault;
- } else if ((store_has_lower_limit && lower_load_has_store_part) ||
- (store_has_upper_limit && upper_load_has_store_part) ||
- (lower_load_has_store_part && upper_load_has_store_part)) {
- // This is the partial store-load forwarding case where a store
- // has only part of the load's data.
-
- // If it's already been written back, then don't worry about
- // stalling on it.
- if (storeQueue[store_idx].completed) {
- continue;
- }
-
- // Must stall load and force it to retry, so long as it's the oldest
- // load that needs to do so.
- if (!stalled ||
- (stalled &&
- loadQueue[load_idx]->seqNum <
- loadQueue[stallingLoadIdx]->seqNum)) {
- stalled = true;
- stallingStoreIsn = storeQueue[store_idx].inst->seqNum;
- stallingLoadIdx = load_idx;
- }
-
- // Tell IQ/mem dep unit that this instruction will need to be
- // rescheduled eventually
- be->rescheduleMemInst(loadQueue[load_idx]);
-
- DPRINTF(OzoneLSQ, "Load-store forwarding mis-match. "
- "Store idx %i to load addr %#x\n",
- store_idx, req->vaddr);
-
- return NoFault;
- }
- }
-
-
- // If there's no forwarding case, then go access memory
- DynInstPtr inst = loadQueue[load_idx];
-
- ++usedPorts;
-
- // if we have a cache, do cache access too
- if (dcacheInterface) {
- if (dcacheInterface->isBlocked()) {
- isLoadBlocked = true;
- // No fault occurred, even though the interface is blocked.
- return NoFault;
- }
-
- DPRINTF(OzoneLSQ, "D-cache: PC:%#x reading from paddr:%#x "
- "vaddr:%#x flags:%i\n",
- inst->readPC(), req->paddr, req->vaddr, req->flags);
-
- // Setup MemReq pointer
- req->cmd = Read;
- req->completionEvent = NULL;
- req->time = curTick;
- assert(!req->data);
- req->data = new uint8_t[64];
-
- assert(!req->completionEvent);
- typedef typename BackEnd::LdWritebackEvent LdWritebackEvent;
-
- LdWritebackEvent *wb = new LdWritebackEvent(loadQueue[load_idx], be);
-
- req->completionEvent = wb;
-
- // Do Cache Access
- MemAccessResult result = dcacheInterface->access(req);
-
- // Ugly hack to get an event scheduled *only* if the access is
- // a miss. We really should add first-class support for this
- // at some point.
- // @todo: Probably should support having no events
- if (result != MA_HIT) {
- DPRINTF(OzoneLSQ, "D-cache miss!\n");
- DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n",
- inst->seqNum);
-
- lastDcacheStall = curTick;
-
- _status = DcacheMissStall;
-
- wb->setDcacheMiss();
-
- } else {
-// DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n",
-// inst->seqNum);
-
- DPRINTF(OzoneLSQ, "D-cache hit!\n");
- }
- } else {
- fatal("Must use D-cache with new memory system");
- }
-
- return NoFault;
-}
-
-template <class Impl>
-template <class T>
-Fault
-OzoneLSQ<Impl>::write(MemReqPtr &req, T &data, int store_idx)
-{
- assert(storeQueue[store_idx].inst);
-
- DPRINTF(OzoneLSQ, "Doing write to store idx %i, addr %#x data %#x"
- " | storeHead:%i [sn:%i]\n",
- store_idx, req->paddr, data, storeHead,
- storeQueue[store_idx].inst->seqNum);
-
- storeQueue[store_idx].req = req;
- storeQueue[store_idx].size = sizeof(T);
- storeQueue[store_idx].data = data;
-
- // This function only writes the data to the store queue, so no fault
- // can happen here.
- return NoFault;
-}
-
-template <class Impl>
-inline bool
-OzoneLSQ<Impl>::loadBlocked()
-{
- bool ret_val = isLoadBlocked;
- isLoadBlocked = false;
- return ret_val;
-}
-
-#endif // __CPU_OZONE_LSQ_UNIT_HH__
diff --git a/cpu/ozone/lsq_unit_impl.hh b/cpu/ozone/lsq_unit_impl.hh
deleted file mode 100644
index 726348d76..000000000
--- a/cpu/ozone/lsq_unit_impl.hh
+++ /dev/null
@@ -1,846 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "arch/isa_traits.hh"
-#include "base/str.hh"
-#include "cpu/ozone/lsq_unit.hh"
-
-template <class Impl>
-OzoneLSQ<Impl>::StoreCompletionEvent::StoreCompletionEvent(int store_idx,
- Event *wb_event,
- OzoneLSQ<Impl> *lsq_ptr)
- : Event(&mainEventQueue),
- storeIdx(store_idx),
- wbEvent(wb_event),
- lsqPtr(lsq_ptr)
-{
- this->setFlags(Event::AutoDelete);
-}
-
-template <class Impl>
-void
-OzoneLSQ<Impl>::StoreCompletionEvent::process()
-{
- DPRINTF(OzoneLSQ, "Cache miss complete for store idx:%i\n", storeIdx);
-
- //lsqPtr->removeMSHR(lsqPtr->storeQueue[storeIdx].inst->seqNum);
-
-// lsqPtr->cpu->wakeCPU();
- if (wbEvent)
- wbEvent->process();
- lsqPtr->completeStore(storeIdx);
-}
-
-template <class Impl>
-const char *
-OzoneLSQ<Impl>::StoreCompletionEvent::description()
-{
- return "LSQ store completion event";
-}
-
-template <class Impl>
-OzoneLSQ<Impl>::OzoneLSQ()
- : loads(0), stores(0), storesToWB(0), stalled(false), isLoadBlocked(false)
-{
-}
-
-template<class Impl>
-void
-OzoneLSQ<Impl>::init(Params *params, unsigned maxLQEntries,
- unsigned maxSQEntries, unsigned id)
-
-{
- DPRINTF(OzoneLSQ, "Creating OzoneLSQ%i object.\n",id);
-
- lsqID = id;
-
- LQEntries = maxLQEntries;
- SQEntries = maxSQEntries;
-
- loadQueue.resize(LQEntries);
- storeQueue.resize(SQEntries);
-
-
- // May want to initialize these entries to NULL
-
- loadHead = loadTail = 0;
-
- storeHead = storeWBIdx = storeTail = 0;
-
- usedPorts = 0;
- cachePorts = params->cachePorts;
-
- dcacheInterface = params->dcacheInterface;
-
- loadFaultInst = storeFaultInst = memDepViolator = NULL;
-}
-
-template<class Impl>
-std::string
-OzoneLSQ<Impl>::name() const
-{
- return "lsqunit";
-}
-
-template<class Impl>
-void
-OzoneLSQ<Impl>::clearLQ()
-{
- loadQueue.clear();
-}
-
-template<class Impl>
-void
-OzoneLSQ<Impl>::clearSQ()
-{
- storeQueue.clear();
-}
-
-template<class Impl>
-void
-OzoneLSQ<Impl>::setPageTable(PageTable *pt_ptr)
-{
- DPRINTF(OzoneLSQ, "Setting the page table pointer.\n");
- pTable = pt_ptr;
-}
-
-template<class Impl>
-void
-OzoneLSQ<Impl>::resizeLQ(unsigned size)
-{
- assert( size >= LQEntries);
-
- if (size > LQEntries) {
- while (size > loadQueue.size()) {
- DynInstPtr dummy;
- loadQueue.push_back(dummy);
- LQEntries++;
- }
- } else {
- LQEntries = size;
- }
-
-}
-
-template<class Impl>
-void
-OzoneLSQ<Impl>::resizeSQ(unsigned size)
-{
- if (size > SQEntries) {
- while (size > storeQueue.size()) {
- SQEntry dummy;
- storeQueue.push_back(dummy);
- SQEntries++;
- }
- } else {
- SQEntries = size;
- }
-}
-
-template <class Impl>
-void
-OzoneLSQ<Impl>::insert(DynInstPtr &inst)
-{
- // Make sure we really have a memory reference.
- assert(inst->isMemRef());
-
- // Make sure it's one of the two classes of memory references.
- assert(inst->isLoad() || inst->isStore());
-
- if (inst->isLoad()) {
- insertLoad(inst);
- } else {
- insertStore(inst);
- }
-
-// inst->setInLSQ();
-}
-
-template <class Impl>
-void
-OzoneLSQ<Impl>::insertLoad(DynInstPtr &load_inst)
-{
- assert((loadTail + 1) % LQEntries != loadHead && loads < LQEntries);
-
- DPRINTF(OzoneLSQ, "Inserting load PC %#x, idx:%i [sn:%lli]\n",
- load_inst->readPC(), loadTail, load_inst->seqNum);
-
- load_inst->lqIdx = loadTail;
-
- if (stores == 0) {
- load_inst->sqIdx = -1;
- } else {
- load_inst->sqIdx = storeTail;
- }
-
- loadQueue[loadTail] = load_inst;
-
- incrLdIdx(loadTail);
-
- ++loads;
-}
-
-template <class Impl>
-void
-OzoneLSQ<Impl>::insertStore(DynInstPtr &store_inst)
-{
- // Make sure it is not full before inserting an instruction.
- assert((storeTail + 1) % SQEntries != storeHead);
- assert(stores < SQEntries);
-
- DPRINTF(OzoneLSQ, "Inserting store PC %#x, idx:%i [sn:%lli]\n",
- store_inst->readPC(), storeTail, store_inst->seqNum);
-
- store_inst->sqIdx = storeTail;
- store_inst->lqIdx = loadTail;
-
- storeQueue[storeTail] = SQEntry(store_inst);
-
- incrStIdx(storeTail);
-
- ++stores;
-
-}
-
-template <class Impl>
-typename Impl::DynInstPtr
-OzoneLSQ<Impl>::getMemDepViolator()
-{
- DynInstPtr temp = memDepViolator;
-
- memDepViolator = NULL;
-
- return temp;
-}
-
-template <class Impl>
-unsigned
-OzoneLSQ<Impl>::numFreeEntries()
-{
- unsigned free_lq_entries = LQEntries - loads;
- unsigned free_sq_entries = SQEntries - stores;
-
- // Both the LQ and SQ entries have an extra dummy entry to differentiate
- // empty/full conditions. Subtract 1 from the free entries.
- if (free_lq_entries < free_sq_entries) {
- return free_lq_entries - 1;
- } else {
- return free_sq_entries - 1;
- }
-}
-
-template <class Impl>
-int
-OzoneLSQ<Impl>::numLoadsReady()
-{
- int load_idx = loadHead;
- int retval = 0;
-
- while (load_idx != loadTail) {
- assert(loadQueue[load_idx]);
-
- if (loadQueue[load_idx]->readyToIssue()) {
- ++retval;
- }
- }
-
- return retval;
-}
-
-#if 0
-template <class Impl>
-Fault
-OzoneLSQ<Impl>::executeLoad()
-{
- Fault load_fault = NoFault;
- DynInstPtr load_inst;
-
- assert(readyLoads.size() != 0);
-
- // Execute a ready load.
- LdMapIt ready_it = readyLoads.begin();
-
- load_inst = (*ready_it).second;
-
- // Execute the instruction, which is held in the data portion of the
- // iterator.
- load_fault = load_inst->execute();
-
- // If it executed successfully, then switch it over to the executed
- // loads list.
- if (load_fault == NoFault) {
- executedLoads[load_inst->seqNum] = load_inst;
-
- readyLoads.erase(ready_it);
- } else {
- loadFaultInst = load_inst;
- }
-
- return load_fault;
-}
-#endif
-
-template <class Impl>
-Fault
-OzoneLSQ<Impl>::executeLoad(DynInstPtr &inst)
-{
- // Execute a specific load.
- Fault load_fault = NoFault;
-
- DPRINTF(OzoneLSQ, "Executing load PC %#x, [sn:%lli]\n",
- inst->readPC(),inst->seqNum);
-
- // Make sure it's really in the list.
- // Normally it should always be in the list. However,
- /* due to a syscall it may not be the list.
-#ifdef DEBUG
- int i = loadHead;
- while (1) {
- if (i == loadTail && !find(inst)) {
- assert(0 && "Load not in the queue!");
- } else if (loadQueue[i] == inst) {
- break;
- }
-
- i = i + 1;
- if (i >= LQEntries) {
- i = 0;
- }
- }
-#endif // DEBUG*/
-
- load_fault = inst->initiateAcc();
-
- // Might want to make sure that I'm not overwriting a previously faulting
- // instruction that hasn't been checked yet.
- // Actually probably want the oldest faulting load
- if (load_fault != NoFault) {
- // Maybe just set it as can commit here, although that might cause
- // some other problems with sending traps to the ROB too quickly.
-// iewStage->instToCommit(inst);
-// iewStage->activityThisCycle();
- }
-
- return load_fault;
-}
-
-template <class Impl>
-Fault
-OzoneLSQ<Impl>::executeLoad(int lq_idx)
-{
- // Very hackish. Not sure the best way to check that this
- // instruction is at the head of the ROB. I should have some sort
- // of extra information here so that I'm not overloading the
- // canCommit signal for 15 different things.
- loadQueue[lq_idx]->setCanCommit();
- Fault ret_fault = executeLoad(loadQueue[lq_idx]);
- loadQueue[lq_idx]->clearCanCommit();
- return ret_fault;
-}
-
-template <class Impl>
-Fault
-OzoneLSQ<Impl>::executeStore(DynInstPtr &store_inst)
-{
- // Make sure that a store exists.
- assert(stores != 0);
-
- int store_idx = store_inst->sqIdx;
-
- DPRINTF(OzoneLSQ, "Executing store PC %#x [sn:%lli]\n",
- store_inst->readPC(), store_inst->seqNum);
-
- // Check the recently completed loads to see if any match this store's
- // address. If so, then we have a memory ordering violation.
- int load_idx = store_inst->lqIdx;
-
- Fault store_fault = store_inst->initiateAcc();
-
- // Store size should now be available. Use it to get proper offset for
- // addr comparisons.
- int size = storeQueue[store_idx].size;
-
- if (size == 0) {
- DPRINTF(OzoneLSQ,"Fault on Store PC %#x, [sn:%lli],Size = 0\n",
- store_inst->readPC(),store_inst->seqNum);
-
- return store_fault;
- }
-
- assert(store_fault == NoFault);
-
- if (!storeFaultInst) {
- if (store_fault != NoFault) {
- panic("Fault in a store instruction!");
- storeFaultInst = store_inst;
- } else if (store_inst->isNonSpeculative()) {
- // Nonspeculative accesses (namely store conditionals)
- // need to set themselves as able to writeback if we
- // haven't had a fault by here.
- storeQueue[store_idx].canWB = true;
-
- ++storesToWB;
- }
- }
-
- if (!memDepViolator) {
- while (load_idx != loadTail) {
- // Actually should only check loads that have actually executed
- // Might be safe because effAddr is set to InvalAddr when the
- // dyn inst is created.
-
- // Must actually check all addrs in the proper size range
- // Which is more correct than needs to be. What if for now we just
- // assume all loads are quad-word loads, and do the addr based
- // on that.
- // @todo: Fix this, magic number being used here
- if ((loadQueue[load_idx]->effAddr >> 8) ==
- (store_inst->effAddr >> 8)) {
- // A load incorrectly passed this store. Squash and refetch.
- // For now return a fault to show that it was unsuccessful.
- memDepViolator = loadQueue[load_idx];
-
- return TheISA::genMachineCheckFault();
- }
-
- incrLdIdx(load_idx);
- }
-
- // If we've reached this point, there was no violation.
- memDepViolator = NULL;
- }
-
- return store_fault;
-}
-
-template <class Impl>
-void
-OzoneLSQ<Impl>::commitLoad()
-{
- assert(loadQueue[loadHead]);
-
- DPRINTF(OzoneLSQ, "[sn:%lli] Committing head load instruction, PC %#x\n",
- loadQueue[loadHead]->seqNum, loadQueue[loadHead]->readPC());
-
-
- loadQueue[loadHead] = NULL;
-
- incrLdIdx(loadHead);
-
- --loads;
-}
-
-template <class Impl>
-void
-OzoneLSQ<Impl>::commitLoad(InstSeqNum &inst)
-{
- // Hopefully I don't use this function too much
- panic("Don't use this function!");
-
- int i = loadHead;
- while (1) {
- if (i == loadTail) {
- assert(0 && "Load not in the queue!");
- } else if (loadQueue[i]->seqNum == inst) {
- break;
- }
-
- ++i;
- if (i >= LQEntries) {
- i = 0;
- }
- }
-
-// loadQueue[i]->removeInLSQ();
- loadQueue[i] = NULL;
- --loads;
-}
-
-template <class Impl>
-void
-OzoneLSQ<Impl>::commitLoads(InstSeqNum &youngest_inst)
-{
- assert(loads == 0 || loadQueue[loadHead]);
-
- while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) {
- commitLoad();
- }
-}
-
-template <class Impl>
-void
-OzoneLSQ<Impl>::commitStores(InstSeqNum &youngest_inst)
-{
- assert(stores == 0 || storeQueue[storeHead].inst);
-
- int store_idx = storeHead;
-
- while (store_idx != storeTail) {
- assert(storeQueue[store_idx].inst);
- if (!storeQueue[store_idx].canWB) {
- if (storeQueue[store_idx].inst->seqNum > youngest_inst) {
- break;
- }
- DPRINTF(OzoneLSQ, "Marking store as able to write back, PC "
- "%#x [sn:%lli]\n",
- storeQueue[store_idx].inst->readPC(),
- storeQueue[store_idx].inst->seqNum);
-
- storeQueue[store_idx].canWB = true;
-
-// --stores;
- ++storesToWB;
- }
-
- incrStIdx(store_idx);
- }
-}
-
-template <class Impl>
-void
-OzoneLSQ<Impl>::writebackStores()
-{
- while (storesToWB > 0 &&
- storeWBIdx != storeTail &&
- storeQueue[storeWBIdx].inst &&
- storeQueue[storeWBIdx].canWB &&
- usedPorts < cachePorts) {
-
- if (storeQueue[storeWBIdx].size == 0) {
- completeStore(storeWBIdx);
-
- incrStIdx(storeWBIdx);
-
- continue;
- }
-
- if (dcacheInterface && dcacheInterface->isBlocked()) {
- DPRINTF(OzoneLSQ, "Unable to write back any more stores, cache"
- " is blocked!\n");
- break;
- }
-
- ++usedPorts;
-
- if (storeQueue[storeWBIdx].inst->isDataPrefetch()) {
- incrStIdx(storeWBIdx);
-
- continue;
- }
-
- assert(storeQueue[storeWBIdx].req);
- assert(!storeQueue[storeWBIdx].committed);
-
- MemReqPtr req = storeQueue[storeWBIdx].req;
- storeQueue[storeWBIdx].committed = true;
-
-// Fault fault = cpu->translateDataReadReq(req);
- req->cmd = Write;
- req->completionEvent = NULL;
- req->time = curTick;
- assert(!req->data);
- req->data = new uint8_t[64];
- memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size);
-
- DPRINTF(OzoneLSQ, "D-Cache: Writing back store idx:%i PC:%#x "
- "to Addr:%#x, data:%#x [sn:%lli]\n",
- storeWBIdx,storeQueue[storeWBIdx].inst->readPC(),
- req->paddr, *(req->data),
- storeQueue[storeWBIdx].inst->seqNum);
-
-// if (fault != NoFault) {
- //What should we do if there is a fault???
- //for now panic
-// panic("Page Table Fault!!!!!\n");
-// }
-
- if (dcacheInterface) {
- MemAccessResult result = dcacheInterface->access(req);
-
- //@todo temp fix for LL/SC (works fine for 1 CPU)
- if (req->flags & LOCKED) {
- req->result=1;
- panic("LL/SC! oh no no support!!!");
- }
-
- if (isStalled() &&
- storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) {
- DPRINTF(OzoneLSQ, "Unstalling, stalling store [sn:%lli] "
- "load idx:%i\n",
- stallingStoreIsn, stallingLoadIdx);
- stalled = false;
- stallingStoreIsn = 0;
- be->replayMemInst(loadQueue[stallingLoadIdx]);
- }
-
- if (result != MA_HIT && dcacheInterface->doEvents()) {
- Event *wb = NULL;
-/*
- typename IEW::LdWritebackEvent *wb = NULL;
- if (req->flags & LOCKED) {
- // Stx_C does not generate a system port transaction.
- req->result=0;
- wb = new typename IEW::LdWritebackEvent(storeQueue[storeWBIdx].inst,
- iewStage);
- }
-*/
- DPRINTF(OzoneLSQ,"D-Cache Write Miss!\n");
-
-// DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n",
-// storeQueue[storeWBIdx].inst->seqNum);
-
- // Will stores need their own kind of writeback events?
- // Do stores even need writeback events?
- assert(!req->completionEvent);
- req->completionEvent = new
- StoreCompletionEvent(storeWBIdx, wb, this);
-
- lastDcacheStall = curTick;
-
- _status = DcacheMissStall;
-
- //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum);
-
- //DPRINTF(OzoneLSQ, "Added MSHR. count = %i\n",mshrSeqNums.size());
-
- // Increment stat here or something
- } else {
- DPRINTF(OzoneLSQ,"D-Cache: Write Hit on idx:%i !\n",
- storeWBIdx);
-
-// DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
-// storeQueue[storeWBIdx].inst->seqNum);
-
- if (req->flags & LOCKED) {
- // Stx_C does not generate a system port transaction.
- req->result=1;
- typename BackEnd::LdWritebackEvent *wb =
- new typename BackEnd::LdWritebackEvent(storeQueue[storeWBIdx].inst,
- be);
- wb->schedule(curTick);
- }
-
- completeStore(storeWBIdx);
- }
-
- incrStIdx(storeWBIdx);
- } else {
- panic("Must HAVE DCACHE!!!!!\n");
- }
- }
-
- // Not sure this should set it to 0.
- usedPorts = 0;
-
- assert(stores >= 0 && storesToWB >= 0);
-}
-
-/*template <class Impl>
-void
-OzoneLSQ<Impl>::removeMSHR(InstSeqNum seqNum)
-{
- list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(),
- mshrSeqNums.end(),
- seqNum);
-
- if (mshr_it != mshrSeqNums.end()) {
- mshrSeqNums.erase(mshr_it);
- DPRINTF(OzoneLSQ, "Removing MSHR. count = %i\n",mshrSeqNums.size());
- }
-}*/
-
-template <class Impl>
-void
-OzoneLSQ<Impl>::squash(const InstSeqNum &squashed_num)
-{
- DPRINTF(OzoneLSQ, "Squashing until [sn:%lli]!"
- "(Loads:%i Stores:%i)\n",squashed_num,loads,stores);
-
- int load_idx = loadTail;
- decrLdIdx(load_idx);
-
- while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) {
-
- // Clear the smart pointer to make sure it is decremented.
- DPRINTF(OzoneLSQ,"Load Instruction PC %#x squashed, "
- "[sn:%lli]\n",
- loadQueue[load_idx]->readPC(),
- loadQueue[load_idx]->seqNum);
-
- if (isStalled() && load_idx == stallingLoadIdx) {
- stalled = false;
- stallingStoreIsn = 0;
- stallingLoadIdx = 0;
- }
-
-// loadQueue[load_idx]->squashed = true;
- loadQueue[load_idx] = NULL;
- --loads;
-
- // Inefficient!
- loadTail = load_idx;
-
- decrLdIdx(load_idx);
- }
-
- int store_idx = storeTail;
- decrStIdx(store_idx);
-
- while (stores != 0 && storeQueue[store_idx].inst->seqNum > squashed_num) {
-
- // Clear the smart pointer to make sure it is decremented.
- DPRINTF(OzoneLSQ,"Store Instruction PC %#x squashed, "
- "idx:%i [sn:%lli]\n",
- storeQueue[store_idx].inst->readPC(),
- store_idx, storeQueue[store_idx].inst->seqNum);
-
- // I don't think this can happen. It should have been cleared by the
- // stalling load.
- if (isStalled() &&
- storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
- panic("Is stalled should have been cleared by stalling load!\n");
- stalled = false;
- stallingStoreIsn = 0;
- }
-
-// storeQueue[store_idx].inst->squashed = true;
- storeQueue[store_idx].inst = NULL;
- storeQueue[store_idx].canWB = 0;
-
- if (storeQueue[store_idx].req) {
- assert(!storeQueue[store_idx].req->completionEvent);
- }
- storeQueue[store_idx].req = NULL;
- --stores;
-
- // Inefficient!
- storeTail = store_idx;
-
- decrStIdx(store_idx);
- }
-}
-
-template <class Impl>
-void
-OzoneLSQ<Impl>::dumpInsts()
-{
- cprintf("Load store queue: Dumping instructions.\n");
- cprintf("Load queue size: %i\n", loads);
- cprintf("Load queue: ");
-
- int load_idx = loadHead;
-
- while (load_idx != loadTail && loadQueue[load_idx]) {
- cprintf("[sn:%lli] %#x ", loadQueue[load_idx]->seqNum,
- loadQueue[load_idx]->readPC());
-
- incrLdIdx(load_idx);
- }
-
- cprintf("\nStore queue size: %i\n", stores);
- cprintf("Store queue: ");
-
- int store_idx = storeHead;
-
- while (store_idx != storeTail && storeQueue[store_idx].inst) {
- cprintf("[sn:%lli] %#x ", storeQueue[store_idx].inst->seqNum,
- storeQueue[store_idx].inst->readPC());
-
- incrStIdx(store_idx);
- }
-
- cprintf("\n");
-}
-
-template <class Impl>
-void
-OzoneLSQ<Impl>::completeStore(int store_idx)
-{
- assert(storeQueue[store_idx].inst);
- storeQueue[store_idx].completed = true;
- --storesToWB;
- // A bit conservative because a store completion may not free up entries,
- // but hopefully avoids two store completions in one cycle from making
- // the CPU tick twice.
-// cpu->activityThisCycle();
-
- if (store_idx == storeHead) {
- do {
- incrStIdx(storeHead);
-
- --stores;
- } while (storeQueue[storeHead].completed &&
- storeHead != storeTail);
-
-// be->updateLSQNextCycle = true;
- }
-
- DPRINTF(OzoneLSQ, "Store head idx:%i\n", storeHead);
-
- if (isStalled() &&
- storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
- DPRINTF(OzoneLSQ, "Unstalling, stalling store [sn:%lli] "
- "load idx:%i\n",
- stallingStoreIsn, stallingLoadIdx);
- stalled = false;
- stallingStoreIsn = 0;
- be->replayMemInst(loadQueue[stallingLoadIdx]);
- }
-}
-
-template <class Impl>
-inline void
-OzoneLSQ<Impl>::incrStIdx(int &store_idx)
-{
- if (++store_idx >= SQEntries)
- store_idx = 0;
-}
-
-template <class Impl>
-inline void
-OzoneLSQ<Impl>::decrStIdx(int &store_idx)
-{
- if (--store_idx < 0)
- store_idx += SQEntries;
-}
-
-template <class Impl>
-inline void
-OzoneLSQ<Impl>::incrLdIdx(int &load_idx)
-{
- if (++load_idx >= LQEntries)
- load_idx = 0;
-}
-
-template <class Impl>
-inline void
-OzoneLSQ<Impl>::decrLdIdx(int &load_idx)
-{
- if (--load_idx < 0)
- load_idx += LQEntries;
-}
diff --git a/cpu/ozone/lw_back_end.cc b/cpu/ozone/lw_back_end.cc
deleted file mode 100644
index 8e9a56ef5..000000000
--- a/cpu/ozone/lw_back_end.cc
+++ /dev/null
@@ -1,5 +0,0 @@
-
-#include "cpu/ozone/lw_back_end_impl.hh"
-#include "cpu/ozone/ozone_impl.hh"
-
-template class LWBackEnd<OzoneImpl>;
diff --git a/cpu/ozone/lw_back_end.hh b/cpu/ozone/lw_back_end.hh
deleted file mode 100644
index 1c03ffb73..000000000
--- a/cpu/ozone/lw_back_end.hh
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_OZONE_LW_BACK_END_HH__
-#define __CPU_OZONE_LW_BACK_END_HH__
-
-#include <list>
-#include <queue>
-#include <set>
-#include <string>
-
-#include "arch/faults.hh"
-#include "base/timebuf.hh"
-#include "cpu/inst_seq.hh"
-#include "cpu/ozone/rename_table.hh"
-#include "cpu/ozone/thread_state.hh"
-#include "mem/functional/functional.hh"
-#include "mem/mem_interface.hh"
-#include "mem/mem_req.hh"
-#include "sim/eventq.hh"
-
-template <class>
-class Checker;
-class ExecContext;
-
-template <class Impl>
-class OzoneThreadState;
-
-template <class Impl>
-class LWBackEnd
-{
- public:
- typedef OzoneThreadState<Impl> Thread;
-
- typedef typename Impl::Params Params;
- typedef typename Impl::DynInst DynInst;
- typedef typename Impl::DynInstPtr DynInstPtr;
- typedef typename Impl::FullCPU FullCPU;
- typedef typename Impl::FrontEnd FrontEnd;
- typedef typename Impl::FullCPU::CommStruct CommStruct;
-
- struct SizeStruct {
- int size;
- };
-
- typedef SizeStruct DispatchToIssue;
- typedef SizeStruct IssueToExec;
- typedef SizeStruct ExecToCommit;
- typedef SizeStruct Writeback;
-
- TimeBuffer<DispatchToIssue> d2i;
- typename TimeBuffer<DispatchToIssue>::wire instsToDispatch;
- TimeBuffer<IssueToExec> i2e;
- typename TimeBuffer<IssueToExec>::wire instsToExecute;
- TimeBuffer<ExecToCommit> e2c;
- TimeBuffer<Writeback> numInstsToWB;
-
- TimeBuffer<CommStruct> *comm;
- typename TimeBuffer<CommStruct>::wire toIEW;
- typename TimeBuffer<CommStruct>::wire fromCommit;
-
- class TrapEvent : public Event {
- private:
- LWBackEnd<Impl> *be;
-
- public:
- TrapEvent(LWBackEnd<Impl> *_be);
-
- void process();
- const char *description();
- };
-
- /** LdWriteback event for a load completion. */
- class LdWritebackEvent : public Event {
- private:
- /** Instruction that is writing back data to the register file. */
- DynInstPtr inst;
- /** Pointer to IEW stage. */
- LWBackEnd *be;
-
- bool dcacheMiss;
-
- public:
- /** Constructs a load writeback event. */
- LdWritebackEvent(DynInstPtr &_inst, LWBackEnd *be);
-
- /** Processes writeback event. */
- virtual void process();
- /** Returns the description of the writeback event. */
- virtual const char *description();
-
- void setDcacheMiss() { dcacheMiss = true; be->addDcacheMiss(inst); }
- };
-
- LWBackEnd(Params *params);
-
- std::string name() const;
-
- void regStats();
-
- void setCPU(FullCPU *cpu_ptr);
-
- void setFrontEnd(FrontEnd *front_end_ptr)
- { frontEnd = front_end_ptr; }
-
- void setXC(ExecContext *xc_ptr)
- { xc = xc_ptr; }
-
- void setThreadState(Thread *thread_ptr)
- { thread = thread_ptr; }
-
- void setCommBuffer(TimeBuffer<CommStruct> *_comm);
-
- void tick();
- void squash();
- void generateXCEvent() { xcSquash = true; }
- void squashFromXC();
- void squashFromTrap();
- void checkInterrupts();
- bool trapSquash;
- bool xcSquash;
-
- template <class T>
- Fault read(MemReqPtr &req, T &data, int load_idx);
-
- template <class T>
- Fault write(MemReqPtr &req, T &data, int store_idx);
-
- Addr readCommitPC() { return commitPC; }
-
- Addr commitPC;
-
- Tick lastCommitCycle;
-
- bool robEmpty() { return instList.empty(); }
-
- bool isFull() { return numInsts >= numROBEntries; }
- bool isBlocked() { return status == Blocked || dispatchStatus == Blocked; }
-
- void fetchFault(Fault &fault);
-
- int wakeDependents(DynInstPtr &inst, bool memory_deps = false);
-
- /** Tells memory dependence unit that a memory instruction needs to be
- * rescheduled. It will re-execute once replayMemInst() is called.
- */
- void rescheduleMemInst(DynInstPtr &inst);
-
- /** Re-executes all rescheduled memory instructions. */
- void replayMemInst(DynInstPtr &inst);
-
- /** Completes memory instruction. */
- void completeMemInst(DynInstPtr &inst) { }
-
- void addDcacheMiss(DynInstPtr &inst)
- {
- waitingMemOps.insert(inst->seqNum);
- numWaitingMemOps++;
- DPRINTF(BE, "Adding a Dcache miss mem op [sn:%lli], total %i\n",
- inst->seqNum, numWaitingMemOps);
- }
-
- void removeDcacheMiss(DynInstPtr &inst)
- {
- assert(waitingMemOps.find(inst->seqNum) != waitingMemOps.end());
- waitingMemOps.erase(inst->seqNum);
- numWaitingMemOps--;
- DPRINTF(BE, "Removing a Dcache miss mem op [sn:%lli], total %i\n",
- inst->seqNum, numWaitingMemOps);
- }
-
- void addWaitingMemOp(DynInstPtr &inst)
- {
- waitingMemOps.insert(inst->seqNum);
- numWaitingMemOps++;
- DPRINTF(BE, "Adding a waiting mem op [sn:%lli], total %i\n",
- inst->seqNum, numWaitingMemOps);
- }
-
- void removeWaitingMemOp(DynInstPtr &inst)
- {
- assert(waitingMemOps.find(inst->seqNum) != waitingMemOps.end());
- waitingMemOps.erase(inst->seqNum);
- numWaitingMemOps--;
- DPRINTF(BE, "Removing a waiting mem op [sn:%lli], total %i\n",
- inst->seqNum, numWaitingMemOps);
- }
-
- void instToCommit(DynInstPtr &inst);
-
- void switchOut();
- void doSwitchOut();
- void takeOverFrom(ExecContext *old_xc = NULL);
-
- bool isSwitchedOut() { return switchedOut; }
-
- private:
- void generateTrapEvent(Tick latency = 0);
- void handleFault(Fault &fault, Tick latency = 0);
- void updateStructures();
- void dispatchInsts();
- void dispatchStall();
- void checkDispatchStatus();
- void executeInsts();
- void commitInsts();
- void addToLSQ(DynInstPtr &inst);
- void writebackInsts();
- bool commitInst(int inst_num);
- void squash(const InstSeqNum &sn);
- void squashDueToBranch(DynInstPtr &inst);
- void squashDueToMemViolation(DynInstPtr &inst);
- void squashDueToMemBlocked(DynInstPtr &inst);
- void updateExeInstStats(DynInstPtr &inst);
- void updateComInstStats(DynInstPtr &inst);
-
- public:
- FullCPU *cpu;
-
- FrontEnd *frontEnd;
-
- ExecContext *xc;
-
- Thread *thread;
-
- enum Status {
- Running,
- Idle,
- DcacheMissStall,
- DcacheMissComplete,
- Blocked,
- TrapPending
- };
-
- Status status;
-
- Status dispatchStatus;
-
- Status commitStatus;
-
- Counter funcExeInst;
-
- private:
- typedef typename Impl::LdstQueue LdstQueue;
-
- LdstQueue LSQ;
- public:
- RenameTable<Impl> commitRenameTable;
-
- RenameTable<Impl> renameTable;
- private:
- class DCacheCompletionEvent : public Event
- {
- private:
- LWBackEnd *be;
-
- public:
- DCacheCompletionEvent(LWBackEnd *_be);
-
- virtual void process();
- virtual const char *description();
- };
-
- friend class DCacheCompletionEvent;
-
- DCacheCompletionEvent cacheCompletionEvent;
-
- MemInterface *dcacheInterface;
-
- MemReqPtr memReq;
-
- // General back end width. Used if the more specific isn't given.
- int width;
-
- // Dispatch width.
- int dispatchWidth;
- int numDispatchEntries;
- int dispatchSize;
-
- int waitingInsts;
-
- int issueWidth;
-
- // Writeback width
- int wbWidth;
-
- // Commit width
- int commitWidth;
-
- /** Index into queue of instructions being written back. */
- unsigned wbNumInst;
-
- /** Cycle number within the queue of instructions being written
- * back. Used in case there are too many instructions writing
- * back at the current cycle and writesbacks need to be scheduled
- * for the future. See comments in instToCommit().
- */
- unsigned wbCycle;
-
- int numROBEntries;
- int numInsts;
-
- std::set<InstSeqNum> waitingMemOps;
- typedef std::set<InstSeqNum>::iterator MemIt;
- int numWaitingMemOps;
- unsigned maxOutstandingMemOps;
-
- bool squashPending;
- InstSeqNum squashSeqNum;
- Addr squashNextPC;
-
- Fault faultFromFetch;
- bool fetchHasFault;
-
- bool switchedOut;
- bool switchPending;
-
- DynInstPtr memBarrier;
-
- private:
- struct pqCompare {
- bool operator() (const DynInstPtr &lhs, const DynInstPtr &rhs) const
- {
- return lhs->seqNum > rhs->seqNum;
- }
- };
-
- typedef typename std::priority_queue<DynInstPtr, std::vector<DynInstPtr>, pqCompare> ReadyInstQueue;
- ReadyInstQueue exeList;
-
- typedef typename std::list<DynInstPtr>::iterator InstListIt;
-
- std::list<DynInstPtr> instList;
- std::list<DynInstPtr> waitingList;
- std::list<DynInstPtr> replayList;
- std::list<DynInstPtr> writeback;
-
- int latency;
-
- int squashLatency;
-
- bool exactFullStall;
-
- // number of cycles stalled for D-cache misses
-/* Stats::Scalar<> dcacheStallCycles;
- Counter lastDcacheStall;
-*/
- Stats::Vector<> rob_cap_events;
- Stats::Vector<> rob_cap_inst_count;
- Stats::Vector<> iq_cap_events;
- Stats::Vector<> iq_cap_inst_count;
- // total number of instructions executed
- Stats::Vector<> exe_inst;
- Stats::Vector<> exe_swp;
- Stats::Vector<> exe_nop;
- Stats::Vector<> exe_refs;
- Stats::Vector<> exe_loads;
- Stats::Vector<> exe_branches;
-
- Stats::Vector<> issued_ops;
-
- // total number of loads forwaded from LSQ stores
- Stats::Vector<> lsq_forw_loads;
-
- // total number of loads ignored due to invalid addresses
- Stats::Vector<> inv_addr_loads;
-
- // total number of software prefetches ignored due to invalid addresses
- Stats::Vector<> inv_addr_swpfs;
- // ready loads blocked due to memory disambiguation
- Stats::Vector<> lsq_blocked_loads;
-
- Stats::Scalar<> lsqInversion;
-
- Stats::Vector<> n_issued_dist;
- Stats::VectorDistribution<> issue_delay_dist;
-
- Stats::VectorDistribution<> queue_res_dist;
-/*
- Stats::Vector<> stat_fu_busy;
- Stats::Vector2d<> stat_fuBusy;
- Stats::Vector<> dist_unissued;
- Stats::Vector2d<> stat_issued_inst_type;
-
- Stats::Formula misspec_cnt;
- Stats::Formula misspec_ipc;
- Stats::Formula issue_rate;
- Stats::Formula issue_stores;
- Stats::Formula issue_op_rate;
- Stats::Formula fu_busy_rate;
- Stats::Formula commit_stores;
- Stats::Formula commit_ipc;
- Stats::Formula commit_ipb;
- Stats::Formula lsq_inv_rate;
-*/
- Stats::Vector<> writeback_count;
- Stats::Vector<> producer_inst;
- Stats::Vector<> consumer_inst;
- Stats::Vector<> wb_penalized;
-
- Stats::Formula wb_rate;
- Stats::Formula wb_fanout;
- Stats::Formula wb_penalized_rate;
-
- // total number of instructions committed
- Stats::Vector<> stat_com_inst;
- Stats::Vector<> stat_com_swp;
- Stats::Vector<> stat_com_refs;
- Stats::Vector<> stat_com_loads;
- Stats::Vector<> stat_com_membars;
- Stats::Vector<> stat_com_branches;
-
- Stats::Distribution<> n_committed_dist;
-
- Stats::Scalar<> commit_eligible_samples;
- Stats::Vector<> commit_eligible;
-
- Stats::Vector<> squashedInsts;
- Stats::Vector<> ROBSquashedInsts;
-
- Stats::Scalar<> ROB_fcount;
- Stats::Formula ROB_full_rate;
-
- Stats::Vector<> ROB_count; // cumulative ROB occupancy
- Stats::Formula ROB_occ_rate;
- Stats::VectorDistribution<> ROB_occ_dist;
- public:
- void dumpInsts();
-
- Checker<DynInstPtr> *checker;
-};
-
-template <class Impl>
-template <class T>
-Fault
-LWBackEnd<Impl>::read(MemReqPtr &req, T &data, int load_idx)
-{
- return LSQ.read(req, data, load_idx);
-}
-
-template <class Impl>
-template <class T>
-Fault
-LWBackEnd<Impl>::write(MemReqPtr &req, T &data, int store_idx)
-{
- return LSQ.write(req, data, store_idx);
-}
-
-#endif // __CPU_OZONE_LW_BACK_END_HH__
diff --git a/cpu/ozone/lw_back_end_impl.hh b/cpu/ozone/lw_back_end_impl.hh
deleted file mode 100644
index 41b4ea24b..000000000
--- a/cpu/ozone/lw_back_end_impl.hh
+++ /dev/null
@@ -1,1693 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/checker/cpu.hh"
-#include "cpu/ozone/lw_back_end.hh"
-#include "encumbered/cpu/full/op_class.hh"
-
-template <class Impl>
-void
-LWBackEnd<Impl>::generateTrapEvent(Tick latency)
-{
- DPRINTF(BE, "Generating trap event\n");
-
- TrapEvent *trap = new TrapEvent(this);
-
- trap->schedule(curTick + cpu->cycles(latency));
-
- thread->trapPending = true;
-}
-
-template <class Impl>
-int
-LWBackEnd<Impl>::wakeDependents(DynInstPtr &inst, bool memory_deps)
-{
- assert(!inst->isSquashed());
- std::vector<DynInstPtr> &dependents = memory_deps ? inst->getMemDeps() :
- inst->getDependents();
- int num_outputs = dependents.size();
-
- DPRINTF(BE, "Waking instruction [sn:%lli] dependents in IQ\n", inst->seqNum);
-
- for (int i = 0; i < num_outputs; i++) {
- DynInstPtr dep_inst = dependents[i];
- if (!memory_deps) {
- dep_inst->markSrcRegReady();
- } else {
- if (!dep_inst->isSquashed())
- dep_inst->markMemInstReady(inst.get());
- }
-
- DPRINTF(BE, "Marking source reg ready [sn:%lli] in IQ\n", dep_inst->seqNum);
-
- if (dep_inst->readyToIssue() && dep_inst->isInROB() &&
- !dep_inst->isNonSpeculative() && !dep_inst->isStoreConditional() &&
- dep_inst->memDepReady() && !dep_inst->isMemBarrier() &&
- !dep_inst->isWriteBarrier()) {
- DPRINTF(BE, "Adding instruction to exeList [sn:%lli]\n",
- dep_inst->seqNum);
- exeList.push(dep_inst);
- if (dep_inst->iqItValid) {
- DPRINTF(BE, "Removing instruction from waiting list\n");
- waitingList.erase(dep_inst->iqIt);
- waitingInsts--;
- dep_inst->iqItValid = false;
- assert(waitingInsts >= 0);
- }
- if (dep_inst->isMemRef()) {
- removeWaitingMemOp(dep_inst);
- DPRINTF(BE, "Issued a waiting mem op [sn:%lli]\n",
- dep_inst->seqNum);
- }
- }
- }
- return num_outputs;
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::rescheduleMemInst(DynInstPtr &inst)
-{
- replayList.push_front(inst);
-}
-
-template <class Impl>
-LWBackEnd<Impl>::TrapEvent::TrapEvent(LWBackEnd<Impl> *_be)
- : Event(&mainEventQueue, CPU_Tick_Pri), be(_be)
-{
- this->setFlags(Event::AutoDelete);
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::TrapEvent::process()
-{
- be->trapSquash = true;
-}
-
-template <class Impl>
-const char *
-LWBackEnd<Impl>::TrapEvent::description()
-{
- return "Trap event";
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::replayMemInst(DynInstPtr &inst)
-{
- bool found_inst = false;
- while (!replayList.empty()) {
- exeList.push(replayList.front());
- if (replayList.front() == inst) {
- found_inst = true;
- }
- replayList.pop_front();
- }
- assert(found_inst);
-}
-
-template<class Impl>
-LWBackEnd<Impl>::LdWritebackEvent::LdWritebackEvent(DynInstPtr &_inst,
- LWBackEnd<Impl> *_be)
- : Event(&mainEventQueue), inst(_inst), be(_be), dcacheMiss(false)
-{
- this->setFlags(Event::AutoDelete);
-}
-
-template<class Impl>
-void
-LWBackEnd<Impl>::LdWritebackEvent::process()
-{
- DPRINTF(BE, "Load writeback event [sn:%lli]\n", inst->seqNum);
-// DPRINTF(Activity, "Activity: Ld Writeback event [sn:%lli]\n", inst->seqNum);
-
- //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum);
-
-// iewStage->wakeCPU();
-
- if (be->isSwitchedOut())
- return;
-
- if (dcacheMiss) {
- be->removeDcacheMiss(inst);
- }
-
- if (inst->isSquashed()) {
- inst = NULL;
- return;
- }
-
- if (!inst->isExecuted()) {
- inst->setExecuted();
-
- // Execute again to copy data to proper place.
- inst->completeAcc();
- }
-
- // Need to insert instruction into queue to commit
- be->instToCommit(inst);
-
- //wroteToTimeBuffer = true;
-// iewStage->activityThisCycle();
-
- inst = NULL;
-}
-
-template<class Impl>
-const char *
-LWBackEnd<Impl>::LdWritebackEvent::description()
-{
- return "Load writeback event";
-}
-
-
-template <class Impl>
-LWBackEnd<Impl>::DCacheCompletionEvent::DCacheCompletionEvent(LWBackEnd *_be)
- : Event(&mainEventQueue, CPU_Tick_Pri), be(_be)
-{
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::DCacheCompletionEvent::process()
-{
-}
-
-template <class Impl>
-const char *
-LWBackEnd<Impl>::DCacheCompletionEvent::description()
-{
- return "Cache completion event";
-}
-
-template <class Impl>
-LWBackEnd<Impl>::LWBackEnd(Params *params)
- : d2i(5, 5), i2e(5, 5), e2c(5, 5), numInstsToWB(5, 5),
- trapSquash(false), xcSquash(false), cacheCompletionEvent(this),
- dcacheInterface(params->dcacheInterface), width(params->backEndWidth),
- exactFullStall(true)
-{
- numROBEntries = params->numROBEntries;
- numInsts = 0;
- numDispatchEntries = 32;
- maxOutstandingMemOps = params->maxOutstandingMemOps;
- numWaitingMemOps = 0;
- waitingInsts = 0;
- switchedOut = false;
- switchPending = false;
-
- LSQ.setBE(this);
-
- // Setup IQ and LSQ with their parameters here.
- instsToDispatch = d2i.getWire(-1);
-
- instsToExecute = i2e.getWire(-1);
-
- dispatchWidth = params->dispatchWidth ? params->dispatchWidth : width;
- issueWidth = params->issueWidth ? params->issueWidth : width;
- wbWidth = params->wbWidth ? params->wbWidth : width;
- commitWidth = params->commitWidth ? params->commitWidth : width;
-
- LSQ.init(params, params->LQEntries, params->SQEntries, 0);
-
- dispatchStatus = Running;
-}
-
-template <class Impl>
-std::string
-LWBackEnd<Impl>::name() const
-{
- return cpu->name() + ".backend";
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::regStats()
-{
- using namespace Stats;
- rob_cap_events
- .init(cpu->number_of_threads)
- .name(name() + ".ROB:cap_events")
- .desc("number of cycles where ROB cap was active")
- .flags(total)
- ;
-
- rob_cap_inst_count
- .init(cpu->number_of_threads)
- .name(name() + ".ROB:cap_inst")
- .desc("number of instructions held up by ROB cap")
- .flags(total)
- ;
-
- iq_cap_events
- .init(cpu->number_of_threads)
- .name(name() +".IQ:cap_events" )
- .desc("number of cycles where IQ cap was active")
- .flags(total)
- ;
-
- iq_cap_inst_count
- .init(cpu->number_of_threads)
- .name(name() + ".IQ:cap_inst")
- .desc("number of instructions held up by IQ cap")
- .flags(total)
- ;
-
-
- exe_inst
- .init(cpu->number_of_threads)
- .name(name() + ".ISSUE:count")
- .desc("number of insts issued")
- .flags(total)
- ;
-
- exe_swp
- .init(cpu->number_of_threads)
- .name(name() + ".ISSUE:swp")
- .desc("number of swp insts issued")
- .flags(total)
- ;
-
- exe_nop
- .init(cpu->number_of_threads)
- .name(name() + ".ISSUE:nop")
- .desc("number of nop insts issued")
- .flags(total)
- ;
-
- exe_refs
- .init(cpu->number_of_threads)
- .name(name() + ".ISSUE:refs")
- .desc("number of memory reference insts issued")
- .flags(total)
- ;
-
- exe_loads
- .init(cpu->number_of_threads)
- .name(name() + ".ISSUE:loads")
- .desc("number of load insts issued")
- .flags(total)
- ;
-
- exe_branches
- .init(cpu->number_of_threads)
- .name(name() + ".ISSUE:branches")
- .desc("Number of branches issued")
- .flags(total)
- ;
-
- issued_ops
- .init(cpu->number_of_threads)
- .name(name() + ".ISSUE:op_count")
- .desc("number of insts issued")
- .flags(total)
- ;
-
-/*
- for (int i=0; i<Num_OpClasses; ++i) {
- stringstream subname;
- subname << opClassStrings[i] << "_delay";
- issue_delay_dist.subname(i, subname.str());
- }
-*/
- //
- // Other stats
- //
- lsq_forw_loads
- .init(cpu->number_of_threads)
- .name(name() + ".LSQ:forw_loads")
- .desc("number of loads forwarded via LSQ")
- .flags(total)
- ;
-
- inv_addr_loads
- .init(cpu->number_of_threads)
- .name(name() + ".ISSUE:addr_loads")
- .desc("number of invalid-address loads")
- .flags(total)
- ;
-
- inv_addr_swpfs
- .init(cpu->number_of_threads)
- .name(name() + ".ISSUE:addr_swpfs")
- .desc("number of invalid-address SW prefetches")
- .flags(total)
- ;
-
- lsq_blocked_loads
- .init(cpu->number_of_threads)
- .name(name() + ".LSQ:blocked_loads")
- .desc("number of ready loads not issued due to memory disambiguation")
- .flags(total)
- ;
-
- lsqInversion
- .name(name() + ".ISSUE:lsq_invert")
- .desc("Number of times LSQ instruction issued early")
- ;
-
- n_issued_dist
- .init(issueWidth + 1)
- .name(name() + ".ISSUE:issued_per_cycle")
- .desc("Number of insts issued each cycle")
- .flags(total | pdf | dist)
- ;
- issue_delay_dist
- .init(Num_OpClasses,0,99,2)
- .name(name() + ".ISSUE:")
- .desc("cycles from operands ready to issue")
- .flags(pdf | cdf)
- ;
-
- queue_res_dist
- .init(Num_OpClasses, 0, 99, 2)
- .name(name() + ".IQ:residence:")
- .desc("cycles from dispatch to issue")
- .flags(total | pdf | cdf )
- ;
- for (int i = 0; i < Num_OpClasses; ++i) {
- queue_res_dist.subname(i, opClassStrings[i]);
- }
-
- writeback_count
- .init(cpu->number_of_threads)
- .name(name() + ".WB:count")
- .desc("cumulative count of insts written-back")
- .flags(total)
- ;
-
- producer_inst
- .init(cpu->number_of_threads)
- .name(name() + ".WB:producers")
- .desc("num instructions producing a value")
- .flags(total)
- ;
-
- consumer_inst
- .init(cpu->number_of_threads)
- .name(name() + ".WB:consumers")
- .desc("num instructions consuming a value")
- .flags(total)
- ;
-
- wb_penalized
- .init(cpu->number_of_threads)
- .name(name() + ".WB:penalized")
- .desc("number of instrctions required to write to 'other' IQ")
- .flags(total)
- ;
-
-
- wb_penalized_rate
- .name(name() + ".WB:penalized_rate")
- .desc ("fraction of instructions written-back that wrote to 'other' IQ")
- .flags(total)
- ;
-
- wb_penalized_rate = wb_penalized / writeback_count;
-
- wb_fanout
- .name(name() + ".WB:fanout")
- .desc("average fanout of values written-back")
- .flags(total)
- ;
-
- wb_fanout = producer_inst / consumer_inst;
-
- wb_rate
- .name(name() + ".WB:rate")
- .desc("insts written-back per cycle")
- .flags(total)
- ;
- wb_rate = writeback_count / cpu->numCycles;
-
- stat_com_inst
- .init(cpu->number_of_threads)
- .name(name() + ".COM:count")
- .desc("Number of instructions committed")
- .flags(total)
- ;
-
- stat_com_swp
- .init(cpu->number_of_threads)
- .name(name() + ".COM:swp_count")
- .desc("Number of s/w prefetches committed")
- .flags(total)
- ;
-
- stat_com_refs
- .init(cpu->number_of_threads)
- .name(name() + ".COM:refs")
- .desc("Number of memory references committed")
- .flags(total)
- ;
-
- stat_com_loads
- .init(cpu->number_of_threads)
- .name(name() + ".COM:loads")
- .desc("Number of loads committed")
- .flags(total)
- ;
-
- stat_com_membars
- .init(cpu->number_of_threads)
- .name(name() + ".COM:membars")
- .desc("Number of memory barriers committed")
- .flags(total)
- ;
-
- stat_com_branches
- .init(cpu->number_of_threads)
- .name(name() + ".COM:branches")
- .desc("Number of branches committed")
- .flags(total)
- ;
- n_committed_dist
- .init(0,commitWidth,1)
- .name(name() + ".COM:committed_per_cycle")
- .desc("Number of insts commited each cycle")
- .flags(pdf)
- ;
-
- //
- // Commit-Eligible instructions...
- //
- // -> The number of instructions eligible to commit in those
- // cycles where we reached our commit BW limit (less the number
- // actually committed)
- //
- // -> The average value is computed over ALL CYCLES... not just
- // the BW limited cycles
- //
- // -> The standard deviation is computed only over cycles where
- // we reached the BW limit
- //
- commit_eligible
- .init(cpu->number_of_threads)
- .name(name() + ".COM:bw_limited")
- .desc("number of insts not committed due to BW limits")
- .flags(total)
- ;
-
- commit_eligible_samples
- .name(name() + ".COM:bw_lim_events")
- .desc("number cycles where commit BW limit reached")
- ;
-
- squashedInsts
- .init(cpu->number_of_threads)
- .name(name() + ".COM:squashed_insts")
- .desc("Number of instructions removed from inst list")
- ;
-
- ROBSquashedInsts
- .init(cpu->number_of_threads)
- .name(name() + ".COM:rob_squashed_insts")
- .desc("Number of instructions removed from inst list when they reached the head of the ROB")
- ;
-
- ROB_fcount
- .name(name() + ".ROB:full_count")
- .desc("number of cycles where ROB was full")
- ;
-
- ROB_count
- .init(cpu->number_of_threads)
- .name(name() + ".ROB:occupancy")
- .desc(name() + ".ROB occupancy (cumulative)")
- .flags(total)
- ;
-
- ROB_full_rate
- .name(name() + ".ROB:full_rate")
- .desc("ROB full per cycle")
- ;
- ROB_full_rate = ROB_fcount / cpu->numCycles;
-
- ROB_occ_rate
- .name(name() + ".ROB:occ_rate")
- .desc("ROB occupancy rate")
- .flags(total)
- ;
- ROB_occ_rate = ROB_count / cpu->numCycles;
-
- ROB_occ_dist
- .init(cpu->number_of_threads,0,numROBEntries,2)
- .name(name() + ".ROB:occ_dist")
- .desc("ROB Occupancy per cycle")
- .flags(total | cdf)
- ;
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::setCPU(FullCPU *cpu_ptr)
-{
- cpu = cpu_ptr;
- LSQ.setCPU(cpu_ptr);
- checker = cpu->checker;
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::setCommBuffer(TimeBuffer<CommStruct> *_comm)
-{
- comm = _comm;
- toIEW = comm->getWire(0);
- fromCommit = comm->getWire(-1);
-}
-
-#if FULL_SYSTEM
-template <class Impl>
-void
-LWBackEnd<Impl>::checkInterrupts()
-{
- if (cpu->checkInterrupts &&
- cpu->check_interrupts() &&
- !cpu->inPalMode(thread->readPC()) &&
- !trapSquash &&
- !xcSquash) {
- frontEnd->interruptPending = true;
- if (robEmpty() && !LSQ.hasStoresToWB()) {
- // Will need to squash all instructions currently in flight and have
- // the interrupt handler restart at the last non-committed inst.
- // Most of that can be handled through the trap() function. The
- // processInterrupts() function really just checks for interrupts
- // and then calls trap() if there is an interrupt present.
-
- // Not sure which thread should be the one to interrupt. For now
- // always do thread 0.
- assert(!thread->inSyscall);
- thread->inSyscall = true;
-
- // CPU will handle implementation of the interrupt.
- cpu->processInterrupts();
-
- // Now squash or record that I need to squash this cycle.
- commitStatus = TrapPending;
-
- // Exit state update mode to avoid accidental updating.
- thread->inSyscall = false;
-
- // Generate trap squash event.
- generateTrapEvent();
-
- DPRINTF(BE, "Interrupt detected.\n");
- } else {
- DPRINTF(BE, "Interrupt must wait for ROB to drain.\n");
- }
- }
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::handleFault(Fault &fault, Tick latency)
-{
- DPRINTF(BE, "Handling fault!\n");
-
- assert(!thread->inSyscall);
-
- thread->inSyscall = true;
-
- // Consider holding onto the trap and waiting until the trap event
- // happens for this to be executed.
- fault->invoke(thread->getXCProxy());
-
- // Exit state update mode to avoid accidental updating.
- thread->inSyscall = false;
-
- commitStatus = TrapPending;
-
- // Generate trap squash event.
- generateTrapEvent(latency);
-}
-#endif
-
-template <class Impl>
-void
-LWBackEnd<Impl>::tick()
-{
- DPRINTF(BE, "Ticking back end\n");
-
- if (switchPending && robEmpty() && !LSQ.hasStoresToWB()) {
- cpu->signalSwitched();
- return;
- }
-
- ROB_count[0]+= numInsts;
-
- wbCycle = 0;
-
- // Read in any done instruction information and update the IQ or LSQ.
- updateStructures();
-
-#if FULL_SYSTEM
- checkInterrupts();
-
- if (trapSquash) {
- assert(!xcSquash);
- squashFromTrap();
- } else if (xcSquash) {
- squashFromXC();
- }
-#endif
-
- if (dispatchStatus != Blocked) {
- dispatchInsts();
- } else {
- checkDispatchStatus();
- }
-
- if (commitStatus != TrapPending) {
- executeInsts();
-
- commitInsts();
- }
-
- LSQ.writebackStores();
-
- DPRINTF(BE, "Waiting insts: %i, mem ops: %i, ROB entries in use: %i, "
- "LSQ loads: %i, LSQ stores: %i\n",
- waitingInsts, numWaitingMemOps, numInsts,
- LSQ.numLoads(), LSQ.numStores());
-
-#ifdef DEBUG
- assert(numInsts == instList.size());
- assert(waitingInsts == waitingList.size());
- assert(numWaitingMemOps == waitingMemOps.size());
- assert(!switchedOut);
-#endif
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::updateStructures()
-{
- if (fromCommit->doneSeqNum) {
- LSQ.commitLoads(fromCommit->doneSeqNum);
- LSQ.commitStores(fromCommit->doneSeqNum);
- }
-
- if (fromCommit->nonSpecSeqNum) {
- if (fromCommit->uncached) {
-// LSQ.executeLoad(fromCommit->lqIdx);
- } else {
-// IQ.scheduleNonSpec(
-// fromCommit->nonSpecSeqNum);
- }
- }
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::addToLSQ(DynInstPtr &inst)
-{
- // Do anything LSQ specific here?
- LSQ.insert(inst);
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::dispatchInsts()
-{
- DPRINTF(BE, "Trying to dispatch instructions.\n");
-
- while (numInsts < numROBEntries &&
- numWaitingMemOps < maxOutstandingMemOps) {
- // Get instruction from front of time buffer
- DynInstPtr inst = frontEnd->getInst();
- if (!inst) {
- break;
- } else if (inst->isSquashed()) {
- continue;
- }
-
- ++numInsts;
- instList.push_front(inst);
-
- inst->setInROB();
-
- DPRINTF(BE, "Dispatching instruction [sn:%lli] PC:%#x\n",
- inst->seqNum, inst->readPC());
-
- for (int i = 0; i < inst->numDestRegs(); ++i)
- renameTable[inst->destRegIdx(i)] = inst;
-
- if (inst->isMemBarrier() || inst->isWriteBarrier()) {
- if (memBarrier) {
- DPRINTF(BE, "Instruction [sn:%lli] is waiting on "
- "barrier [sn:%lli].\n",
- inst->seqNum, memBarrier->seqNum);
- memBarrier->addMemDependent(inst);
- inst->addSrcMemInst(memBarrier);
- }
- memBarrier = inst;
- inst->setCanCommit();
- } else if (inst->readyToIssue() &&
- !inst->isNonSpeculative() &&
- !inst->isStoreConditional()) {
- if (inst->isMemRef()) {
-
- LSQ.insert(inst);
- if (memBarrier) {
- DPRINTF(BE, "Instruction [sn:%lli] is waiting on "
- "barrier [sn:%lli].\n",
- inst->seqNum, memBarrier->seqNum);
- memBarrier->addMemDependent(inst);
- inst->addSrcMemInst(memBarrier);
- addWaitingMemOp(inst);
-
- waitingList.push_front(inst);
- inst->iqIt = waitingList.begin();
- inst->iqItValid = true;
- waitingInsts++;
- } else {
- DPRINTF(BE, "Instruction [sn:%lli] ready, addding to "
- "exeList.\n",
- inst->seqNum);
- exeList.push(inst);
- }
- } else if (inst->isNop()) {
- DPRINTF(BE, "Nop encountered [sn:%lli], skipping exeList.\n",
- inst->seqNum);
- inst->setIssued();
- inst->setExecuted();
- inst->setCanCommit();
- } else {
- DPRINTF(BE, "Instruction [sn:%lli] ready, addding to "
- "exeList.\n",
- inst->seqNum);
- exeList.push(inst);
- }
- } else {
- if (inst->isNonSpeculative() || inst->isStoreConditional()) {
- inst->setCanCommit();
- DPRINTF(BE, "Adding non speculative instruction\n");
- }
-
- if (inst->isMemRef()) {
- addWaitingMemOp(inst);
- LSQ.insert(inst);
- if (memBarrier) {
- memBarrier->addMemDependent(inst);
- inst->addSrcMemInst(memBarrier);
-
- DPRINTF(BE, "Instruction [sn:%lli] is waiting on "
- "barrier [sn:%lli].\n",
- inst->seqNum, memBarrier->seqNum);
- }
- }
-
- DPRINTF(BE, "Instruction [sn:%lli] not ready, addding to "
- "waitingList.\n",
- inst->seqNum);
- waitingList.push_front(inst);
- inst->iqIt = waitingList.begin();
- inst->iqItValid = true;
- waitingInsts++;
- }
- }
-
- // Check if IQ or LSQ is full. If so we'll need to break and stop
- // removing instructions. Also update the number of insts to remove
- // from the queue. Check here if we don't care about exact stall
- // conditions.
-/*
- bool stall = false;
- if (IQ.isFull()) {
- DPRINTF(BE, "IQ is full!\n");
- stall = true;
- } else if (LSQ.isFull()) {
- DPRINTF(BE, "LSQ is full!\n");
- stall = true;
- } else if (isFull()) {
- DPRINTF(BE, "ROB is full!\n");
- stall = true;
- ROB_fcount++;
- }
- if (stall) {
- d2i.advance();
- dispatchStall();
- return;
- }
-*/
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::dispatchStall()
-{
- dispatchStatus = Blocked;
- if (!cpu->decoupledFrontEnd) {
- // Tell front end to stall here through a timebuffer, or just tell
- // it directly.
- }
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::checkDispatchStatus()
-{
- DPRINTF(BE, "Checking dispatch status\n");
- assert(dispatchStatus == Blocked);
- if (!LSQ.isFull() && !isFull()) {
- DPRINTF(BE, "Dispatch no longer blocked\n");
- dispatchStatus = Running;
- dispatchInsts();
- }
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::executeInsts()
-{
- DPRINTF(BE, "Trying to execute instructions\n");
-
- int num_executed = 0;
- while (!exeList.empty() && num_executed < issueWidth) {
- DynInstPtr inst = exeList.top();
-
- DPRINTF(BE, "Executing inst [sn:%lli] PC: %#x\n",
- inst->seqNum, inst->readPC());
-
- // Check if the instruction is squashed; if so then skip it
- // and don't count it towards the FU usage.
- if (inst->isSquashed()) {
- DPRINTF(BE, "Execute: Instruction was squashed.\n");
-
- // Not sure how to handle this plus the method of sending # of
- // instructions to use. Probably will just have to count it
- // towards the bandwidth usage, but not the FU usage.
- ++num_executed;
-
- // Consider this instruction executed so that commit can go
- // ahead and retire the instruction.
- inst->setExecuted();
-
- // Not sure if I should set this here or just let commit try to
- // commit any squashed instructions. I like the latter a bit more.
- inst->setCanCommit();
-
-// ++iewExecSquashedInsts;
- exeList.pop();
-
- continue;
- }
-
- Fault fault = NoFault;
-
- // Execute instruction.
- // Note that if the instruction faults, it will be handled
- // at the commit stage.
- if (inst->isMemRef() &&
- (!inst->isDataPrefetch() && !inst->isInstPrefetch())) {
- if (dcacheInterface->isBlocked()) {
- // Should I move the instruction aside?
- DPRINTF(BE, "Execute: dcache is blocked\n");
- break;
- }
- DPRINTF(BE, "Execute: Initiating access for memory "
- "reference.\n");
-
- if (inst->isLoad()) {
- LSQ.executeLoad(inst);
- } else if (inst->isStore()) {
- LSQ.executeStore(inst);
- if (inst->req && !(inst->req->flags & LOCKED)) {
- inst->setExecuted();
-
- instToCommit(inst);
- }
- } else {
- panic("Unknown mem type!");
- }
- } else {
- inst->execute();
-
- inst->setExecuted();
-
- instToCommit(inst);
- }
-
- updateExeInstStats(inst);
-
- ++funcExeInst;
- ++num_executed;
-
- exeList.pop();
-
- if (inst->mispredicted()) {
- squashDueToBranch(inst);
- break;
- } else if (LSQ.violation()) {
- // Get the DynInst that caused the violation. Note that this
- // clears the violation signal.
- DynInstPtr violator;
- violator = LSQ.getMemDepViolator();
-
- DPRINTF(BE, "LDSTQ detected a violation. Violator PC: "
- "%#x, inst PC: %#x. Addr is: %#x.\n",
- violator->readPC(), inst->readPC(), inst->physEffAddr);
-
- // Squash.
- squashDueToMemViolation(inst);
- }
- }
-
- issued_ops[0]+= num_executed;
- n_issued_dist[num_executed]++;
-}
-
-template<class Impl>
-void
-LWBackEnd<Impl>::instToCommit(DynInstPtr &inst)
-{
-
- DPRINTF(BE, "Sending instructions to commit [sn:%lli] PC %#x.\n",
- inst->seqNum, inst->readPC());
-
- if (!inst->isSquashed()) {
- DPRINTF(BE, "Writing back instruction [sn:%lli] PC %#x.\n",
- inst->seqNum, inst->readPC());
-
- inst->setCanCommit();
-
- if (inst->isExecuted()) {
- inst->setResultReady();
- int dependents = wakeDependents(inst);
- if (dependents) {
- producer_inst[0]++;
- consumer_inst[0]+= dependents;
- }
- }
- }
-
- writeback_count[0]++;
-}
-#if 0
-template <class Impl>
-void
-LWBackEnd<Impl>::writebackInsts()
-{
- int wb_width = wbWidth;
- // Using this method I'm not quite sure how to prevent an
- // instruction from waking its own dependents multiple times,
- // without the guarantee that commit always has enough bandwidth
- // to accept all instructions being written back. This guarantee
- // might not be too unrealistic.
- InstListIt wb_inst_it = writeback.begin();
- InstListIt wb_end_it = writeback.end();
- int inst_num = 0;
- int consumer_insts = 0;
-
- for (; inst_num < wb_width &&
- wb_inst_it != wb_end_it; inst_num++) {
- DynInstPtr inst = (*wb_inst_it);
-
- // Some instructions will be sent to commit without having
- // executed because they need commit to handle them.
- // E.g. Uncached loads have not actually executed when they
- // are first sent to commit. Instead commit must tell the LSQ
- // when it's ready to execute the uncached load.
- if (!inst->isSquashed()) {
- DPRINTF(BE, "Writing back instruction [sn:%lli] PC %#x.\n",
- inst->seqNum, inst->readPC());
-
- inst->setCanCommit();
- inst->setResultReady();
-
- if (inst->isExecuted()) {
- int dependents = wakeDependents(inst);
- if (dependents) {
- producer_inst[0]++;
- consumer_insts+= dependents;
- }
- }
- }
-
- writeback.erase(wb_inst_it++);
- }
- LSQ.writebackStores();
- consumer_inst[0]+= consumer_insts;
- writeback_count[0]+= inst_num;
-}
-#endif
-template <class Impl>
-bool
-LWBackEnd<Impl>::commitInst(int inst_num)
-{
- // Read instruction from the head of the ROB
- DynInstPtr inst = instList.back();
-
- // Make sure instruction is valid
- assert(inst);
-
- if (!inst->readyToCommit())
- return false;
-
- DPRINTF(BE, "Trying to commit instruction [sn:%lli] PC:%#x\n",
- inst->seqNum, inst->readPC());
-
- thread->setPC(inst->readPC());
- thread->setNextPC(inst->readNextPC());
- inst->reachedCommit = true;
-
- // If the instruction is not executed yet, then it is a non-speculative
- // or store inst. Signal backwards that it should be executed.
- if (!inst->isExecuted()) {
- if (inst->isNonSpeculative() ||
- inst->isStoreConditional() ||
- inst->isMemBarrier() ||
- inst->isWriteBarrier()) {
-#if !FULL_SYSTEM
- // Hack to make sure syscalls aren't executed until all stores
- // write back their data. This direct communication shouldn't
- // be used for anything other than this.
- if (inst_num > 0 || LSQ.hasStoresToWB())
-#else
- if ((inst->isMemBarrier() || inst->isWriteBarrier() ||
- inst->isQuiesce()) &&
- LSQ.hasStoresToWB())
-#endif
- {
- DPRINTF(BE, "Waiting for all stores to writeback.\n");
- return false;
- }
-
- DPRINTF(BE, "Encountered a store or non-speculative "
- "instruction at the head of the ROB, PC %#x.\n",
- inst->readPC());
-
- if (inst->isMemBarrier() || inst->isWriteBarrier()) {
- DPRINTF(BE, "Waking dependents on barrier [sn:%lli]\n",
- inst->seqNum);
- assert(memBarrier);
- wakeDependents(inst, true);
- if (memBarrier == inst)
- memBarrier = NULL;
- inst->clearMemDependents();
- }
-
- // Send back the non-speculative instruction's sequence number.
- if (inst->iqItValid) {
- DPRINTF(BE, "Removing instruction from waiting list\n");
- waitingList.erase(inst->iqIt);
- inst->iqItValid = false;
- waitingInsts--;
- assert(waitingInsts >= 0);
- if (inst->isStore())
- removeWaitingMemOp(inst);
- }
-
- exeList.push(inst);
-
- // Change the instruction so it won't try to commit again until
- // it is executed.
- inst->clearCanCommit();
-
-// ++commitNonSpecStalls;
-
- return false;
- } else if (inst->isLoad()) {
- DPRINTF(BE, "[sn:%lli]: Uncached load, PC %#x.\n",
- inst->seqNum, inst->readPC());
-
- // Send back the non-speculative instruction's sequence
- // number. Maybe just tell the lsq to re-execute the load.
-
- // Send back the non-speculative instruction's sequence number.
- if (inst->iqItValid) {
- DPRINTF(BE, "Removing instruction from waiting list\n");
- waitingList.erase(inst->iqIt);
- inst->iqItValid = false;
- waitingInsts--;
- assert(waitingInsts >= 0);
- removeWaitingMemOp(inst);
- }
- replayMemInst(inst);
-
- inst->clearCanCommit();
-
- return false;
- } else {
- panic("Trying to commit un-executed instruction "
- "of unknown type!\n");
- }
- }
-
- // Not handled for now.
- assert(!inst->isThreadSync());
- assert(inst->memDepReady());
- // Stores will mark themselves as totally completed as they need
- // to wait to writeback to memory. @todo: Hack...attempt to fix
- // having the checker be forced to wait until a store completes in
- // order to check all of the instructions. If the store at the
- // head of the check list misses, but a later store hits, then
- // loads in the checker may see the younger store values instead
- // of the store they should see. Either the checker needs its own
- // memory (annoying to update), its own store buffer (how to tell
- // which value is correct?), or something else...
- if (!inst->isStore()) {
- inst->setCompleted();
- }
- // Check if the instruction caused a fault. If so, trap.
- Fault inst_fault = inst->getFault();
-
- // Use checker prior to updating anything due to traps or PC
- // based events.
- if (checker) {
- checker->tick(inst);
- }
-
- if (inst_fault != NoFault) {
- DPRINTF(BE, "Inst [sn:%lli] PC %#x has a fault\n",
- inst->seqNum, inst->readPC());
-
- // Instruction is completed as it has a fault.
- inst->setCompleted();
-
- if (LSQ.hasStoresToWB()) {
- DPRINTF(BE, "Stores still in flight, will wait until drained.\n");
- return false;
- } else if (inst_num != 0) {
- DPRINTF(BE, "Will wait until instruction is head of commit group.\n");
- return false;
- } else if (checker && inst->isStore()) {
- checker->tick(inst);
- }
-
- thread->setInst(
- static_cast<TheISA::MachInst>(inst->staticInst->machInst));
-#if FULL_SYSTEM
- handleFault(inst_fault);
- return false;
-#else // !FULL_SYSTEM
- panic("fault (%d) detected @ PC %08p", inst_fault,
- inst->PC);
-#endif // FULL_SYSTEM
- }
-
- int freed_regs = 0;
-
- for (int i = 0; i < inst->numDestRegs(); ++i) {
- DPRINTF(BE, "Commit rename map setting reg %i to [sn:%lli]\n",
- (int)inst->destRegIdx(i), inst->seqNum);
- thread->renameTable[inst->destRegIdx(i)] = inst;
- ++freed_regs;
- }
-
- if (inst->traceData) {
- inst->traceData->setFetchSeq(inst->seqNum);
- inst->traceData->setCPSeq(thread->numInst);
- inst->traceData->finalize();
- inst->traceData = NULL;
- }
-
- inst->clearDependents();
-
- frontEnd->addFreeRegs(freed_regs);
-
- instList.pop_back();
-
- --numInsts;
- ++thread->funcExeInst;
- // Maybe move this to where the fault is handled; if the fault is
- // handled, don't try to set this myself as the fault will set it.
- // If not, then I set thread->PC = thread->nextPC and
- // thread->nextPC = thread->nextPC + 4.
- thread->setPC(thread->readNextPC());
- thread->setNextPC(thread->readNextPC() + sizeof(TheISA::MachInst));
- updateComInstStats(inst);
-
- // Write the done sequence number here.
- toIEW->doneSeqNum = inst->seqNum;
- lastCommitCycle = curTick;
-
-#if FULL_SYSTEM
- int count = 0;
- Addr oldpc;
- do {
- if (count == 0)
- assert(!thread->inSyscall && !thread->trapPending);
- oldpc = thread->readPC();
- cpu->system->pcEventQueue.service(
- thread->getXCProxy());
- count++;
- } while (oldpc != thread->readPC());
- if (count > 1) {
- DPRINTF(BE, "PC skip function event, stopping commit\n");
- xcSquash = true;
- return false;
- }
-#endif
- return true;
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::commitInsts()
-{
- // Not sure this should be a loop or not.
- int inst_num = 0;
- while (!instList.empty() && inst_num < commitWidth) {
- if (instList.back()->isSquashed()) {
- instList.back()->clearDependents();
- instList.pop_back();
- --numInsts;
- ROBSquashedInsts[instList.back()->threadNumber]++;
- continue;
- }
-
- if (!commitInst(inst_num++)) {
- DPRINTF(BE, "Can't commit, Instruction [sn:%lli] PC "
- "%#x is head of ROB and not ready\n",
- instList.back()->seqNum, instList.back()->readPC());
- --inst_num;
- break;
- }
- }
- n_committed_dist.sample(inst_num);
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::squash(const InstSeqNum &sn)
-{
- LSQ.squash(sn);
-
- int freed_regs = 0;
- InstListIt waiting_list_end = waitingList.end();
- InstListIt insts_it = waitingList.begin();
-
- while (insts_it != waiting_list_end && (*insts_it)->seqNum > sn)
- {
- if ((*insts_it)->isSquashed()) {
- ++insts_it;
- continue;
- }
- DPRINTF(BE, "Squashing instruction on waitingList PC %#x, [sn:%lli].\n",
- (*insts_it)->readPC(),
- (*insts_it)->seqNum);
-
- if ((*insts_it)->isMemRef()) {
- DPRINTF(BE, "Squashing a waiting mem op [sn:%lli]\n",
- (*insts_it)->seqNum);
- removeWaitingMemOp((*insts_it));
- }
-
- waitingList.erase(insts_it++);
- waitingInsts--;
- }
- assert(waitingInsts >= 0);
-
- insts_it = instList.begin();
-
- while (!instList.empty() && (*insts_it)->seqNum > sn)
- {
- if ((*insts_it)->isSquashed()) {
- ++insts_it;
- continue;
- }
- DPRINTF(BE, "Squashing instruction on inst list PC %#x, [sn:%lli].\n",
- (*insts_it)->readPC(),
- (*insts_it)->seqNum);
-
- // Mark the instruction as squashed, and ready to commit so that
- // it can drain out of the pipeline.
- (*insts_it)->setSquashed();
-
- (*insts_it)->setCanCommit();
-
- (*insts_it)->removeInROB();
-
- for (int i = 0; i < (*insts_it)->numDestRegs(); ++i) {
- DynInstPtr prev_dest = (*insts_it)->getPrevDestInst(i);
- DPRINTF(BE, "Commit rename map setting reg %i to [sn:%lli]\n",
- (int)(*insts_it)->destRegIdx(i), prev_dest->seqNum);
- renameTable[(*insts_it)->destRegIdx(i)] = prev_dest;
- ++freed_regs;
- }
-
- (*insts_it)->clearDependents();
-
- squashedInsts[(*insts_it)->threadNumber]++;
-
- instList.erase(insts_it++);
- --numInsts;
- }
-
- insts_it = waitingList.begin();
- while (!waitingList.empty() && insts_it != waitingList.end()) {
- if ((*insts_it)->seqNum < sn) {
- ++insts_it;
- continue;
- }
- assert((*insts_it)->isSquashed());
-
- waitingList.erase(insts_it++);
- waitingInsts--;
- }
-
- while (memBarrier && memBarrier->seqNum > sn) {
- DPRINTF(BE, "[sn:%lli] Memory barrier squashed (or previously "
- "squashed)\n", memBarrier->seqNum);
- memBarrier->clearMemDependents();
- if (memBarrier->memDepReady()) {
- DPRINTF(BE, "No previous barrier\n");
- memBarrier = NULL;
- } else {
- std::list<DynInstPtr> &srcs = memBarrier->getMemSrcs();
- memBarrier = srcs.front();
- srcs.pop_front();
- assert(srcs.empty());
- DPRINTF(BE, "Previous barrier: [sn:%lli]\n",
- memBarrier->seqNum);
- }
- }
-
- frontEnd->addFreeRegs(freed_regs);
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::squashFromXC()
-{
- InstSeqNum squashed_inst = robEmpty() ? 0 : instList.back()->seqNum - 1;
- squash(squashed_inst);
- frontEnd->squash(squashed_inst, thread->readPC(),
- false, false);
- frontEnd->interruptPending = false;
-
- thread->trapPending = false;
- thread->inSyscall = false;
- xcSquash = false;
- commitStatus = Running;
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::squashFromTrap()
-{
- InstSeqNum squashed_inst = robEmpty() ? 0 : instList.back()->seqNum - 1;
- squash(squashed_inst);
- frontEnd->squash(squashed_inst, thread->readPC(),
- false, false);
- frontEnd->interruptPending = false;
-
- thread->trapPending = false;
- thread->inSyscall = false;
- trapSquash = false;
- commitStatus = Running;
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::squashDueToBranch(DynInstPtr &inst)
-{
- // Update the branch predictor state I guess
- DPRINTF(BE, "Squashing due to branch [sn:%lli], will restart at PC %#x\n",
- inst->seqNum, inst->readNextPC());
- squash(inst->seqNum);
- frontEnd->squash(inst->seqNum, inst->readNextPC(),
- true, inst->mispredicted());
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::squashDueToMemViolation(DynInstPtr &inst)
-{
- // Update the branch predictor state I guess
- DPRINTF(BE, "Squashing due to violation [sn:%lli], will restart at PC %#x\n",
- inst->seqNum, inst->readNextPC());
- squash(inst->seqNum);
- frontEnd->squash(inst->seqNum, inst->readNextPC(),
- false, inst->mispredicted());
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::squashDueToMemBlocked(DynInstPtr &inst)
-{
- DPRINTF(IEW, "Memory blocked, squashing load and younger insts, "
- "PC: %#x [sn:%i].\n", inst->readPC(), inst->seqNum);
-
- squash(inst->seqNum - 1);
- frontEnd->squash(inst->seqNum - 1, inst->readPC());
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::fetchFault(Fault &fault)
-{
- faultFromFetch = fault;
- fetchHasFault = true;
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::switchOut()
-{
- switchPending = true;
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::doSwitchOut()
-{
- switchedOut = true;
- switchPending = false;
- // Need to get rid of all committed, non-speculative state and write it
- // to memory/XC. In this case this is stores that have committed and not
- // yet written back.
- assert(robEmpty());
- assert(!LSQ.hasStoresToWB());
-
- LSQ.switchOut();
-
- squash(0);
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::takeOverFrom(ExecContext *old_xc)
-{
- switchedOut = false;
- xcSquash = false;
- trapSquash = false;
-
- numInsts = 0;
- numWaitingMemOps = 0;
- waitingMemOps.clear();
- waitingInsts = 0;
- switchedOut = false;
- dispatchStatus = Running;
- commitStatus = Running;
- LSQ.takeOverFrom(old_xc);
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::updateExeInstStats(DynInstPtr &inst)
-{
- int thread_number = inst->threadNumber;
-
- //
- // Pick off the software prefetches
- //
-#ifdef TARGET_ALPHA
- if (inst->isDataPrefetch())
- exe_swp[thread_number]++;
- else
- exe_inst[thread_number]++;
-#else
- exe_inst[thread_number]++;
-#endif
-
- //
- // Control operations
- //
- if (inst->isControl())
- exe_branches[thread_number]++;
-
- //
- // Memory operations
- //
- if (inst->isMemRef()) {
- exe_refs[thread_number]++;
-
- if (inst->isLoad())
- exe_loads[thread_number]++;
- }
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::updateComInstStats(DynInstPtr &inst)
-{
- unsigned tid = inst->threadNumber;
-
- // keep an instruction count
- thread->numInst++;
- thread->numInsts++;
-
- cpu->numInst++;
- //
- // Pick off the software prefetches
- //
-#ifdef TARGET_ALPHA
- if (inst->isDataPrefetch()) {
- stat_com_swp[tid]++;
- } else {
- stat_com_inst[tid]++;
- }
-#else
- stat_com_inst[tid]++;
-#endif
-
- //
- // Control Instructions
- //
- if (inst->isControl())
- stat_com_branches[tid]++;
-
- //
- // Memory references
- //
- if (inst->isMemRef()) {
- stat_com_refs[tid]++;
-
- if (inst->isLoad()) {
- stat_com_loads[tid]++;
- }
- }
-
- if (inst->isMemBarrier()) {
- stat_com_membars[tid]++;
- }
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::dumpInsts()
-{
- int num = 0;
- int valid_num = 0;
-
- InstListIt inst_list_it = --(instList.end());
-
- cprintf("ExeList size: %i\n", exeList.size());
-
- cprintf("Inst list size: %i\n", instList.size());
-
- while (inst_list_it != instList.end())
- {
- cprintf("Instruction:%i\n",
- num);
- if (!(*inst_list_it)->isSquashed()) {
- if (!(*inst_list_it)->isIssued()) {
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- } else if ((*inst_list_it)->isMemRef() &&
- !(*inst_list_it)->memOpDone) {
- // Loads that have not been marked as executed still count
- // towards the total instructions.
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- }
- }
-
- cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
- "Issued:%i\nSquashed:%i\n",
- (*inst_list_it)->readPC(),
- (*inst_list_it)->seqNum,
- (*inst_list_it)->threadNumber,
- (*inst_list_it)->isIssued(),
- (*inst_list_it)->isSquashed());
-
- if ((*inst_list_it)->isMemRef()) {
- cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
- }
-
- cprintf("\n");
-
- inst_list_it--;
- ++num;
- }
-
- cprintf("Waiting list size: %i\n", waitingList.size());
-
- inst_list_it = --(waitingList.end());
-
- while (inst_list_it != waitingList.end())
- {
- cprintf("Instruction:%i\n",
- num);
- if (!(*inst_list_it)->isSquashed()) {
- if (!(*inst_list_it)->isIssued()) {
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- } else if ((*inst_list_it)->isMemRef() &&
- !(*inst_list_it)->memOpDone) {
- // Loads that have not been marked as executed still count
- // towards the total instructions.
- ++valid_num;
- cprintf("Count:%i\n", valid_num);
- }
- }
-
- cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
- "Issued:%i\nSquashed:%i\n",
- (*inst_list_it)->readPC(),
- (*inst_list_it)->seqNum,
- (*inst_list_it)->threadNumber,
- (*inst_list_it)->isIssued(),
- (*inst_list_it)->isSquashed());
-
- if ((*inst_list_it)->isMemRef()) {
- cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
- }
-
- cprintf("\n");
-
- inst_list_it--;
- ++num;
- }
-
- cprintf("waitingMemOps list size: %i\n", waitingMemOps.size());
-
- MemIt waiting_it = waitingMemOps.begin();
-
- while (waiting_it != waitingMemOps.end())
- {
- cprintf("[sn:%lli] ", (*waiting_it));
- waiting_it++;
- ++num;
- }
- cprintf("\n");
-}
diff --git a/cpu/ozone/lw_lsq.cc b/cpu/ozone/lw_lsq.cc
deleted file mode 100644
index 922228b09..000000000
--- a/cpu/ozone/lw_lsq.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "cpu/ozone/ozone_impl.hh"
-#include "cpu/ozone/lw_lsq_impl.hh"
-
-// Force the instantiation of LDSTQ for all the implementations we care about.
-template class OzoneLWLSQ<OzoneImpl>;
-
diff --git a/cpu/ozone/lw_lsq.hh b/cpu/ozone/lw_lsq.hh
deleted file mode 100644
index 6fe343b42..000000000
--- a/cpu/ozone/lw_lsq.hh
+++ /dev/null
@@ -1,657 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_OZONE_LW_LSQ_HH__
-#define __CPU_OZONE_LW_LSQ_HH__
-
-#include <list>
-#include <map>
-#include <queue>
-#include <algorithm>
-
-#include "arch/faults.hh"
-#include "arch/isa_traits.hh"
-#include "config/full_system.hh"
-#include "base/hashmap.hh"
-#include "cpu/inst_seq.hh"
-#include "mem/mem_interface.hh"
-//#include "mem/page_table.hh"
-#include "sim/debug.hh"
-#include "sim/sim_object.hh"
-
-//class PageTable;
-
-/**
- * Class that implements the actual LQ and SQ for each specific thread.
- * Both are circular queues; load entries are freed upon committing, while
- * store entries are freed once they writeback. The LSQUnit tracks if there
- * are memory ordering violations, and also detects partial load to store
- * forwarding cases (a store only has part of a load's data) that requires
- * the load to wait until the store writes back. In the former case it
- * holds onto the instruction until the dependence unit looks at it, and
- * in the latter it stalls the LSQ until the store writes back. At that
- * point the load is replayed.
- */
-template <class Impl>
-class OzoneLWLSQ {
- public:
- typedef typename Impl::Params Params;
- typedef typename Impl::FullCPU FullCPU;
- typedef typename Impl::BackEnd BackEnd;
- typedef typename Impl::DynInstPtr DynInstPtr;
- typedef typename Impl::IssueStruct IssueStruct;
-
- typedef TheISA::IntReg IntReg;
-
- typedef typename std::map<InstSeqNum, DynInstPtr>::iterator LdMapIt;
-
- private:
- class StoreCompletionEvent : public Event {
- public:
- /** Constructs a store completion event. */
- StoreCompletionEvent(DynInstPtr &inst, BackEnd *be,
- Event *wb_event, OzoneLWLSQ *lsq_ptr);
-
- /** Processes the store completion event. */
- void process();
-
- /** Returns the description of this event. */
- const char *description();
-
- private:
- /** The store index of the store being written back. */
- DynInstPtr inst;
-
- BackEnd *be;
- /** The writeback event for the store. Needed for store
- * conditionals.
- */
- public:
- Event *wbEvent;
- bool miss;
- private:
- /** The pointer to the LSQ unit that issued the store. */
- OzoneLWLSQ<Impl> *lsqPtr;
- };
-
- public:
- /** Constructs an LSQ unit. init() must be called prior to use. */
- OzoneLWLSQ();
-
- /** Initializes the LSQ unit with the specified number of entries. */
- void init(Params *params, unsigned maxLQEntries,
- unsigned maxSQEntries, unsigned id);
-
- /** Returns the name of the LSQ unit. */
- std::string name() const;
-
- /** Sets the CPU pointer. */
- void setCPU(FullCPU *cpu_ptr)
- { cpu = cpu_ptr; }
-
- /** Sets the back-end stage pointer. */
- void setBE(BackEnd *be_ptr)
- { be = be_ptr; }
-
- /** Sets the page table pointer. */
-// void setPageTable(PageTable *pt_ptr);
-
- /** Ticks the LSQ unit, which in this case only resets the number of
- * used cache ports.
- * @todo: Move the number of used ports up to the LSQ level so it can
- * be shared by all LSQ units.
- */
- void tick() { usedPorts = 0; }
-
- /** Inserts an instruction. */
- void insert(DynInstPtr &inst);
- /** Inserts a load instruction. */
- void insertLoad(DynInstPtr &load_inst);
- /** Inserts a store instruction. */
- void insertStore(DynInstPtr &store_inst);
-
- /** Executes a load instruction. */
- Fault executeLoad(DynInstPtr &inst);
-
- /** Executes a store instruction. */
- Fault executeStore(DynInstPtr &inst);
-
- /** Commits the head load. */
- void commitLoad();
- /** Commits loads older than a specific sequence number. */
- void commitLoads(InstSeqNum &youngest_inst);
-
- /** Commits stores older than a specific sequence number. */
- void commitStores(InstSeqNum &youngest_inst);
-
- /** Writes back stores. */
- void writebackStores();
-
- // @todo: Include stats in the LSQ unit.
- //void regStats();
-
- /** Clears all the entries in the LQ. */
- void clearLQ();
-
- /** Clears all the entries in the SQ. */
- void clearSQ();
-
- /** Resizes the LQ to a given size. */
- void resizeLQ(unsigned size);
-
- /** Resizes the SQ to a given size. */
- void resizeSQ(unsigned size);
-
- /** Squashes all instructions younger than a specific sequence number. */
- void squash(const InstSeqNum &squashed_num);
-
- /** Returns if there is a memory ordering violation. Value is reset upon
- * call to getMemDepViolator().
- */
- bool violation() { return memDepViolator; }
-
- /** Returns the memory ordering violator. */
- DynInstPtr getMemDepViolator();
-
- /** Returns if a load became blocked due to the memory system. It clears
- * the bool's value upon this being called.
- */
- bool loadBlocked()
- { return isLoadBlocked; }
-
- void clearLoadBlocked()
- { isLoadBlocked = false; }
-
- bool isLoadBlockedHandled()
- { return loadBlockedHandled; }
-
- void setLoadBlockedHandled()
- { loadBlockedHandled = true; }
-
- /** Returns the number of free entries (min of free LQ and SQ entries). */
- unsigned numFreeEntries();
-
- /** Returns the number of loads ready to execute. */
- int numLoadsReady();
-
- /** Returns the number of loads in the LQ. */
- int numLoads() { return loads; }
-
- /** Returns the number of stores in the SQ. */
- int numStores() { return stores; }
-
- /** Returns if either the LQ or SQ is full. */
- bool isFull() { return lqFull() || sqFull(); }
-
- /** Returns if the LQ is full. */
- bool lqFull() { return loads >= (LQEntries - 1); }
-
- /** Returns if the SQ is full. */
- bool sqFull() { return stores >= (SQEntries - 1); }
-
- /** Debugging function to dump instructions in the LSQ. */
- void dumpInsts();
-
- /** Returns the number of instructions in the LSQ. */
- unsigned getCount() { return loads + stores; }
-
- /** Returns if there are any stores to writeback. */
- bool hasStoresToWB() { return storesToWB; }
-
- /** Returns the number of stores to writeback. */
- int numStoresToWB() { return storesToWB; }
-
- /** Returns if the LSQ unit will writeback on this cycle. */
- bool willWB() { return storeQueue.back().canWB &&
- !storeQueue.back().completed &&
- !dcacheInterface->isBlocked(); }
-
- void switchOut();
-
- void takeOverFrom(ExecContext *old_xc = NULL);
-
- bool isSwitchedOut() { return switchedOut; }
-
- bool switchedOut;
-
- private:
- /** Completes the store at the specified index. */
- void completeStore(int store_idx);
-
- private:
- /** Pointer to the CPU. */
- FullCPU *cpu;
-
- /** Pointer to the back-end stage. */
- BackEnd *be;
-
- /** Pointer to the D-cache. */
- MemInterface *dcacheInterface;
-
- /** Pointer to the page table. */
-// PageTable *pTable;
-
- public:
- struct SQEntry {
- /** Constructs an empty store queue entry. */
- SQEntry()
- : inst(NULL), req(NULL), size(0), data(0),
- canWB(0), committed(0), completed(0), lqIt(NULL)
- { }
-
- /** Constructs a store queue entry for a given instruction. */
- SQEntry(DynInstPtr &_inst)
- : inst(_inst), req(NULL), size(0), data(0),
- canWB(0), committed(0), completed(0), lqIt(NULL)
- { }
-
- /** The store instruction. */
- DynInstPtr inst;
- /** The memory request for the store. */
- MemReqPtr req;
- /** The size of the store. */
- int size;
- /** The store data. */
- IntReg data;
- /** Whether or not the store can writeback. */
- bool canWB;
- /** Whether or not the store is committed. */
- bool committed;
- /** Whether or not the store is completed. */
- bool completed;
-
- typename std::list<DynInstPtr>::iterator lqIt;
- };
-
- enum Status {
- Running,
- Idle,
- DcacheMissStall,
- DcacheMissSwitch
- };
-
- private:
- /** The OzoneLWLSQ thread id. */
- unsigned lsqID;
-
- /** The status of the LSQ unit. */
- Status _status;
-
- /** The store queue. */
- std::list<SQEntry> storeQueue;
- /** The load queue. */
- std::list<DynInstPtr> loadQueue;
-
- typedef typename std::list<SQEntry>::iterator SQIt;
- typedef typename std::list<DynInstPtr>::iterator LQIt;
-
-
- struct HashFn {
- size_t operator() (const int a) const
- {
- unsigned hash = (((a >> 14) ^ ((a >> 2) & 0xffff))) & 0x7FFFFFFF;
-
- return hash;
- }
- };
-
- m5::hash_map<int, SQIt, HashFn> SQItHash;
- std::queue<int> SQIndices;
- m5::hash_map<int, LQIt, HashFn> LQItHash;
- std::queue<int> LQIndices;
-
- typedef typename m5::hash_map<int, LQIt, HashFn>::iterator LQHashIt;
- typedef typename m5::hash_map<int, SQIt, HashFn>::iterator SQHashIt;
- // Consider making these 16 bits
- /** The number of LQ entries. */
- unsigned LQEntries;
- /** The number of SQ entries. */
- unsigned SQEntries;
-
- /** The number of load instructions in the LQ. */
- int loads;
- /** The number of store instructions in the SQ (excludes those waiting to
- * writeback).
- */
- int stores;
-
- int storesToWB;
-
- /// @todo Consider moving to a more advanced model with write vs read ports
- /** The number of cache ports available each cycle. */
- int cachePorts;
-
- /** The number of used cache ports in this cycle. */
- int usedPorts;
-
- //list<InstSeqNum> mshrSeqNums;
-
- //Stats::Scalar<> dcacheStallCycles;
- Counter lastDcacheStall;
-
- // Make these per thread?
- /** Whether or not the LSQ is stalled. */
- bool stalled;
- /** The store that causes the stall due to partial store to load
- * forwarding.
- */
- InstSeqNum stallingStoreIsn;
- /** The index of the above store. */
- LQIt stallingLoad;
-
- /** Whether or not a load is blocked due to the memory system. It is
- * cleared when this value is checked via loadBlocked().
- */
- bool isLoadBlocked;
-
- bool loadBlockedHandled;
-
- InstSeqNum blockedLoadSeqNum;
-
- /** The oldest faulting load instruction. */
- DynInstPtr loadFaultInst;
- /** The oldest faulting store instruction. */
- DynInstPtr storeFaultInst;
-
- /** The oldest load that caused a memory ordering violation. */
- DynInstPtr memDepViolator;
-
- // Will also need how many read/write ports the Dcache has. Or keep track
- // of that in stage that is one level up, and only call executeLoad/Store
- // the appropriate number of times.
-
- public:
- /** Executes the load at the given index. */
- template <class T>
- Fault read(MemReqPtr &req, T &data, int load_idx);
-
- /** Executes the store at the given index. */
- template <class T>
- Fault write(MemReqPtr &req, T &data, int store_idx);
-
- /** Returns the sequence number of the head load instruction. */
- InstSeqNum getLoadHeadSeqNum()
- {
- if (!loadQueue.empty()) {
- return loadQueue.back()->seqNum;
- } else {
- return 0;
- }
-
- }
-
- /** Returns the sequence number of the head store instruction. */
- InstSeqNum getStoreHeadSeqNum()
- {
- if (!storeQueue.empty()) {
- return storeQueue.back().inst->seqNum;
- } else {
- return 0;
- }
-
- }
-
- /** Returns whether or not the LSQ unit is stalled. */
- bool isStalled() { return stalled; }
-};
-
-template <class Impl>
-template <class T>
-Fault
-OzoneLWLSQ<Impl>::read(MemReqPtr &req, T &data, int load_idx)
-{
- //Depending on issue2execute delay a squashed load could
- //execute if it is found to be squashed in the same
- //cycle it is scheduled to execute
- typename m5::hash_map<int, LQIt, HashFn>::iterator
- lq_hash_it = LQItHash.find(load_idx);
- assert(lq_hash_it != LQItHash.end());
- DynInstPtr inst = (*(*lq_hash_it).second);
-
- if (inst->isExecuted()) {
- panic("Should not reach this point with split ops!");
-
- memcpy(&data,req->data,req->size);
-
- return NoFault;
- }
-
- // Make sure this isn't an uncacheable access
- // A bit of a hackish way to get uncached accesses to work only if they're
- // at the head of the LSQ and are ready to commit (at the head of the ROB
- // too).
- // @todo: Fix uncached accesses.
- if (req->flags & UNCACHEABLE &&
- (inst != loadQueue.back() || !inst->reachedCommit)) {
- DPRINTF(OzoneLSQ, "[sn:%lli] Uncached load and not head of "
- "commit/LSQ!\n",
- inst->seqNum);
- be->rescheduleMemInst(inst);
- return TheISA::genMachineCheckFault();
- }
-
- // Check the SQ for any previous stores that might lead to forwarding
- SQIt sq_it = storeQueue.begin();
- int store_size = 0;
-
- DPRINTF(OzoneLSQ, "Read called, load idx: %i addr: %#x\n",
- load_idx, req->paddr);
-
- while (sq_it != storeQueue.end() && (*sq_it).inst->seqNum > inst->seqNum)
- ++sq_it;
-
- while (1) {
- // End once we've reached the top of the LSQ
- if (sq_it == storeQueue.end()) {
- break;
- }
-
- assert((*sq_it).inst);
-
- store_size = (*sq_it).size;
-
- if (store_size == 0) {
- sq_it++;
- continue;
- }
-
- // Check if the store data is within the lower and upper bounds of
- // addresses that the request needs.
- bool store_has_lower_limit =
- req->vaddr >= (*sq_it).inst->effAddr;
- bool store_has_upper_limit =
- (req->vaddr + req->size) <= ((*sq_it).inst->effAddr +
- store_size);
- bool lower_load_has_store_part =
- req->vaddr < ((*sq_it).inst->effAddr +
- store_size);
- bool upper_load_has_store_part =
- (req->vaddr + req->size) > (*sq_it).inst->effAddr;
-
- // If the store's data has all of the data needed, we can forward.
- if (store_has_lower_limit && store_has_upper_limit) {
-
- int shift_amt = req->vaddr & (store_size - 1);
- // Assumes byte addressing
- shift_amt = shift_amt << 3;
-
- // Cast this to type T?
- data = (*sq_it).data >> shift_amt;
-
- req->cmd = Read;
- assert(!req->completionEvent);
- req->completionEvent = NULL;
- req->time = curTick;
- assert(!req->data);
- req->data = new uint8_t[64];
-
- memcpy(req->data, &data, req->size);
-
- DPRINTF(OzoneLSQ, "Forwarding from store [sn:%lli] to load to "
- "[sn:%lli] addr %#x, data %#x\n",
- (*sq_it).inst->seqNum, inst->seqNum, req->vaddr, *(req->data));
-
- typename BackEnd::LdWritebackEvent *wb =
- new typename BackEnd::LdWritebackEvent(inst,
- be);
-
- // We'll say this has a 1 cycle load-store forwarding latency
- // for now.
- // FIXME - Need to make this a parameter.
- wb->schedule(curTick);
-
- // Should keep track of stat for forwarded data
- return NoFault;
- } else if ((store_has_lower_limit && lower_load_has_store_part) ||
- (store_has_upper_limit && upper_load_has_store_part) ||
- (lower_load_has_store_part && upper_load_has_store_part)) {
- // This is the partial store-load forwarding case where a store
- // has only part of the load's data.
-
- // If it's already been written back, then don't worry about
- // stalling on it.
- if ((*sq_it).completed) {
- sq_it++;
- break;
- }
-
- // Must stall load and force it to retry, so long as it's the oldest
- // load that needs to do so.
- if (!stalled ||
- (stalled &&
- inst->seqNum <
- (*stallingLoad)->seqNum)) {
- stalled = true;
- stallingStoreIsn = (*sq_it).inst->seqNum;
- stallingLoad = (*lq_hash_it).second;
- }
-
- // Tell IQ/mem dep unit that this instruction will need to be
- // rescheduled eventually
- be->rescheduleMemInst(inst);
-
- DPRINTF(OzoneLSQ, "Load-store forwarding mis-match. "
- "Store [sn:%lli] to load addr %#x\n",
- (*sq_it).inst->seqNum, req->vaddr);
-
- return NoFault;
- }
- sq_it++;
- }
-
- // If there's no forwarding case, then go access memory
- DPRINTF(OzoneLSQ, "Doing functional access for inst PC %#x\n",
- inst->readPC());
-
- // Setup MemReq pointer
- req->cmd = Read;
- req->completionEvent = NULL;
- req->time = curTick;
- assert(!req->data);
- req->data = new uint8_t[64];
- Fault fault = cpu->read(req, data);
- memcpy(req->data, &data, sizeof(T));
-
- ++usedPorts;
-
- // if we have a cache, do cache access too
- if (dcacheInterface) {
- if (dcacheInterface->isBlocked()) {
- // There's an older load that's already going to squash.
- if (isLoadBlocked && blockedLoadSeqNum < inst->seqNum)
- return NoFault;
-
- isLoadBlocked = true;
- loadBlockedHandled = false;
- blockedLoadSeqNum = inst->seqNum;
- // No fault occurred, even though the interface is blocked.
- return NoFault;
- }
-
- DPRINTF(OzoneLSQ, "D-cache: PC:%#x reading from paddr:%#x "
- "vaddr:%#x flags:%i\n",
- inst->readPC(), req->paddr, req->vaddr, req->flags);
-
- assert(!req->completionEvent);
- req->completionEvent =
- new typename BackEnd::LdWritebackEvent(inst, be);
-
- // Do Cache Access
- MemAccessResult result = dcacheInterface->access(req);
-
- // Ugly hack to get an event scheduled *only* if the access is
- // a miss. We really should add first-class support for this
- // at some point.
- // @todo: Probably should support having no events
- if (result != MA_HIT) {
- DPRINTF(OzoneLSQ, "D-cache miss!\n");
- DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n",
- inst->seqNum);
-
- lastDcacheStall = curTick;
-
- _status = DcacheMissStall;
-
- } else {
- DPRINTF(OzoneLSQ, "D-cache hit!\n");
- }
- } else {
- fatal("Must use D-cache with new memory system");
- }
-
- return NoFault;
-}
-
-template <class Impl>
-template <class T>
-Fault
-OzoneLWLSQ<Impl>::write(MemReqPtr &req, T &data, int store_idx)
-{
- SQHashIt sq_hash_it = SQItHash.find(store_idx);
- assert(sq_hash_it != SQItHash.end());
-
- SQIt sq_it = (*sq_hash_it).second;
- assert((*sq_it).inst);
-
- DPRINTF(OzoneLSQ, "Doing write to store idx %i, addr %#x data %#x"
- " | [sn:%lli]\n",
- store_idx, req->paddr, data, (*sq_it).inst->seqNum);
-
- (*sq_it).req = req;
- (*sq_it).size = sizeof(T);
- (*sq_it).data = data;
- assert(!req->data);
- req->data = new uint8_t[64];
- memcpy(req->data, (uint8_t *)&(*sq_it).data, req->size);
-
- // This function only writes the data to the store queue, so no fault
- // can happen here.
- return NoFault;
-}
-
-#endif // __CPU_OZONE_LW_LSQ_HH__
diff --git a/cpu/ozone/lw_lsq_impl.hh b/cpu/ozone/lw_lsq_impl.hh
deleted file mode 100644
index f72bbb1cc..000000000
--- a/cpu/ozone/lw_lsq_impl.hh
+++ /dev/null
@@ -1,874 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "arch/isa_traits.hh"
-#include "base/str.hh"
-#include "cpu/ozone/lw_lsq.hh"
-#include "cpu/checker/cpu.hh"
-
-template <class Impl>
-OzoneLWLSQ<Impl>::StoreCompletionEvent::StoreCompletionEvent(DynInstPtr &_inst,
- BackEnd *_be,
- Event *wb_event,
- OzoneLWLSQ<Impl> *lsq_ptr)
- : Event(&mainEventQueue),
- inst(_inst),
- be(_be),
- wbEvent(wb_event),
- miss(false),
- lsqPtr(lsq_ptr)
-{
- this->setFlags(Event::AutoDelete);
-}
-
-template <class Impl>
-void
-OzoneLWLSQ<Impl>::StoreCompletionEvent::process()
-{
- DPRINTF(OzoneLSQ, "Cache miss complete for store [sn:%lli]\n",
- inst->seqNum);
-
- //lsqPtr->removeMSHR(lsqPtr->storeQueue[storeIdx].inst->seqNum);
-
-// lsqPtr->cpu->wakeCPU();
- if (lsqPtr->isSwitchedOut()) {
- if (wbEvent)
- delete wbEvent;
-
- return;
- }
-
- if (wbEvent) {
- wbEvent->process();
- delete wbEvent;
- }
-
- lsqPtr->completeStore(inst->sqIdx);
- if (miss)
- be->removeDcacheMiss(inst);
-}
-
-template <class Impl>
-const char *
-OzoneLWLSQ<Impl>::StoreCompletionEvent::description()
-{
- return "LSQ store completion event";
-}
-
-template <class Impl>
-OzoneLWLSQ<Impl>::OzoneLWLSQ()
- : loads(0), stores(0), storesToWB(0), stalled(false), isLoadBlocked(false),
- loadBlockedHandled(false)
-{
-}
-
-template<class Impl>
-void
-OzoneLWLSQ<Impl>::init(Params *params, unsigned maxLQEntries,
- unsigned maxSQEntries, unsigned id)
-{
- DPRINTF(OzoneLSQ, "Creating OzoneLWLSQ%i object.\n",id);
-
- lsqID = id;
-
- LQEntries = maxLQEntries;
- SQEntries = maxSQEntries;
-
- for (int i = 0; i < LQEntries * 2; i++) {
- LQIndices.push(i);
- SQIndices.push(i);
- }
-
- usedPorts = 0;
- cachePorts = params->cachePorts;
-
- dcacheInterface = params->dcacheInterface;
-
- loadFaultInst = storeFaultInst = memDepViolator = NULL;
-
- blockedLoadSeqNum = 0;
-}
-
-template<class Impl>
-std::string
-OzoneLWLSQ<Impl>::name() const
-{
- return "lsqunit";
-}
-
-template<class Impl>
-void
-OzoneLWLSQ<Impl>::clearLQ()
-{
- loadQueue.clear();
-}
-
-template<class Impl>
-void
-OzoneLWLSQ<Impl>::clearSQ()
-{
- storeQueue.clear();
-}
-/*
-template<class Impl>
-void
-OzoneLWLSQ<Impl>::setPageTable(PageTable *pt_ptr)
-{
- DPRINTF(OzoneLSQ, "Setting the page table pointer.\n");
- pTable = pt_ptr;
-}
-*/
-template<class Impl>
-void
-OzoneLWLSQ<Impl>::resizeLQ(unsigned size)
-{
- assert( size >= LQEntries);
-
- if (size > LQEntries) {
- while (size > loadQueue.size()) {
- DynInstPtr dummy;
- loadQueue.push_back(dummy);
- LQEntries++;
- }
- } else {
- LQEntries = size;
- }
-
-}
-
-template<class Impl>
-void
-OzoneLWLSQ<Impl>::resizeSQ(unsigned size)
-{
- if (size > SQEntries) {
- while (size > storeQueue.size()) {
- SQEntry dummy;
- storeQueue.push_back(dummy);
- SQEntries++;
- }
- } else {
- SQEntries = size;
- }
-}
-
-template <class Impl>
-void
-OzoneLWLSQ<Impl>::insert(DynInstPtr &inst)
-{
- // Make sure we really have a memory reference.
- assert(inst->isMemRef());
-
- // Make sure it's one of the two classes of memory references.
- assert(inst->isLoad() || inst->isStore());
-
- if (inst->isLoad()) {
- insertLoad(inst);
- } else {
- insertStore(inst);
- }
-}
-
-template <class Impl>
-void
-OzoneLWLSQ<Impl>::insertLoad(DynInstPtr &load_inst)
-{
- assert(loads < LQEntries * 2);
- assert(!LQIndices.empty());
- int load_index = LQIndices.front();
- LQIndices.pop();
-
- DPRINTF(OzoneLSQ, "Inserting load PC %#x, idx:%i [sn:%lli]\n",
- load_inst->readPC(), load_index, load_inst->seqNum);
-
- load_inst->lqIdx = load_index;
-
- loadQueue.push_front(load_inst);
- LQItHash[load_index] = loadQueue.begin();
-
- ++loads;
-}
-
-template <class Impl>
-void
-OzoneLWLSQ<Impl>::insertStore(DynInstPtr &store_inst)
-{
- // Make sure it is not full before inserting an instruction.
- assert(stores - storesToWB < SQEntries);
-
- assert(!SQIndices.empty());
- int store_index = SQIndices.front();
- SQIndices.pop();
-
- DPRINTF(OzoneLSQ, "Inserting store PC %#x, idx:%i [sn:%lli]\n",
- store_inst->readPC(), store_index, store_inst->seqNum);
-
- store_inst->sqIdx = store_index;
- SQEntry entry(store_inst);
- if (loadQueue.empty()) {
- entry.lqIt = loadQueue.end();
- } else {
- entry.lqIt = loadQueue.begin();
- }
- storeQueue.push_front(entry);
-
- SQItHash[store_index] = storeQueue.begin();
-
- ++stores;
-}
-
-template <class Impl>
-typename Impl::DynInstPtr
-OzoneLWLSQ<Impl>::getMemDepViolator()
-{
- DynInstPtr temp = memDepViolator;
-
- memDepViolator = NULL;
-
- return temp;
-}
-
-template <class Impl>
-unsigned
-OzoneLWLSQ<Impl>::numFreeEntries()
-{
- unsigned free_lq_entries = LQEntries - loads;
- unsigned free_sq_entries = SQEntries - stores;
-
- // Both the LQ and SQ entries have an extra dummy entry to differentiate
- // empty/full conditions. Subtract 1 from the free entries.
- if (free_lq_entries < free_sq_entries) {
- return free_lq_entries - 1;
- } else {
- return free_sq_entries - 1;
- }
-}
-
-template <class Impl>
-int
-OzoneLWLSQ<Impl>::numLoadsReady()
-{
- int retval = 0;
- LQIt lq_it = loadQueue.begin();
- LQIt end_it = loadQueue.end();
-
- while (lq_it != end_it) {
- if ((*lq_it)->readyToIssue()) {
- ++retval;
- }
- }
-
- return retval;
-}
-
-template <class Impl>
-Fault
-OzoneLWLSQ<Impl>::executeLoad(DynInstPtr &inst)
-{
- // Execute a specific load.
- Fault load_fault = NoFault;
-
- DPRINTF(OzoneLSQ, "Executing load PC %#x, [sn:%lli]\n",
- inst->readPC(),inst->seqNum);
-
- // Make sure it's really in the list.
- // Normally it should always be in the list. However,
- /* due to a syscall it may not be the list.
-#ifdef DEBUG
- int i = loadHead;
- while (1) {
- if (i == loadTail && !find(inst)) {
- assert(0 && "Load not in the queue!");
- } else if (loadQueue[i] == inst) {
- break;
- }
-
- i = i + 1;
- if (i >= LQEntries) {
- i = 0;
- }
- }
-#endif // DEBUG*/
-
- load_fault = inst->initiateAcc();
-
- // Might want to make sure that I'm not overwriting a previously faulting
- // instruction that hasn't been checked yet.
- // Actually probably want the oldest faulting load
- if (load_fault != NoFault) {
- DPRINTF(OzoneLSQ, "Load [sn:%lli] has a fault\n", inst->seqNum);
- // Maybe just set it as can commit here, although that might cause
- // some other problems with sending traps to the ROB too quickly.
- be->instToCommit(inst);
-// iewStage->activityThisCycle();
- }
-
- return load_fault;
-}
-
-template <class Impl>
-Fault
-OzoneLWLSQ<Impl>::executeStore(DynInstPtr &store_inst)
-{
- // Make sure that a store exists.
- assert(stores != 0);
-
- int store_idx = store_inst->sqIdx;
- SQHashIt sq_hash_it = SQItHash.find(store_idx);
- assert(sq_hash_it != SQItHash.end());
- DPRINTF(OzoneLSQ, "Executing store PC %#x [sn:%lli]\n",
- store_inst->readPC(), store_inst->seqNum);
-
- SQIt sq_it = (*sq_hash_it).second;
-
- Fault store_fault = store_inst->initiateAcc();
-
- // Store size should now be available. Use it to get proper offset for
- // addr comparisons.
- int size = (*sq_it).size;
-
- if (size == 0) {
- DPRINTF(OzoneLSQ,"Fault on Store PC %#x, [sn:%lli],Size = 0\n",
- store_inst->readPC(),store_inst->seqNum);
-
- return store_fault;
- }
-
- assert(store_fault == NoFault);
-
- if (!storeFaultInst) {
- if (store_fault != NoFault) {
- panic("Fault in a store instruction!");
- storeFaultInst = store_inst;
- } else if (store_inst->isStoreConditional()) {
- // Store conditionals need to set themselves as able to
- // writeback if we haven't had a fault by here.
- (*sq_it).canWB = true;
-
- ++storesToWB;
- DPRINTF(OzoneLSQ, "Nonspeculative store! storesToWB:%i\n",
- storesToWB);
- }
- }
-
- LQIt lq_it = --(loadQueue.end());
-
- if (!memDepViolator) {
- while (lq_it != loadQueue.end()) {
- if ((*lq_it)->seqNum < store_inst->seqNum) {
- lq_it--;
- continue;
- }
- // Actually should only check loads that have actually executed
- // Might be safe because effAddr is set to InvalAddr when the
- // dyn inst is created.
-
- // Must actually check all addrs in the proper size range
- // Which is more correct than needs to be. What if for now we just
- // assume all loads are quad-word loads, and do the addr based
- // on that.
- // @todo: Fix this, magic number being used here
- if (((*lq_it)->effAddr >> 8) ==
- (store_inst->effAddr >> 8)) {
- // A load incorrectly passed this store. Squash and refetch.
- // For now return a fault to show that it was unsuccessful.
- memDepViolator = (*lq_it);
-
- return TheISA::genMachineCheckFault();
- }
-
- lq_it--;
- }
-
- // If we've reached this point, there was no violation.
- memDepViolator = NULL;
- }
-
- return store_fault;
-}
-
-template <class Impl>
-void
-OzoneLWLSQ<Impl>::commitLoad()
-{
- assert(!loadQueue.empty());
-
- DPRINTF(OzoneLSQ, "[sn:%lli] Committing head load instruction, PC %#x\n",
- loadQueue.back()->seqNum, loadQueue.back()->readPC());
-
- LQIndices.push(loadQueue.back()->lqIdx);
- LQItHash.erase(loadQueue.back()->lqIdx);
-
- loadQueue.pop_back();
-
- --loads;
-}
-
-template <class Impl>
-void
-OzoneLWLSQ<Impl>::commitLoads(InstSeqNum &youngest_inst)
-{
- assert(loads == 0 || !loadQueue.empty());
-
- while (loads != 0 &&
- loadQueue.back()->seqNum <= youngest_inst) {
- commitLoad();
- }
-}
-
-template <class Impl>
-void
-OzoneLWLSQ<Impl>::commitStores(InstSeqNum &youngest_inst)
-{
- assert(stores == 0 || !storeQueue.empty());
-
- SQIt sq_it = --(storeQueue.end());
- while (!storeQueue.empty() && sq_it != storeQueue.end()) {
- assert((*sq_it).inst);
- if (!(*sq_it).canWB) {
- if ((*sq_it).inst->seqNum > youngest_inst) {
- break;
- }
- ++storesToWB;
-
- DPRINTF(OzoneLSQ, "Marking store as able to write back, PC "
- "%#x [sn:%lli], storesToWB:%i\n",
- (*sq_it).inst->readPC(),
- (*sq_it).inst->seqNum,
- storesToWB);
-
- (*sq_it).canWB = true;
- }
-
- sq_it--;
- }
-}
-
-template <class Impl>
-void
-OzoneLWLSQ<Impl>::writebackStores()
-{
- SQIt sq_it = --(storeQueue.end());
- while (storesToWB > 0 &&
- sq_it != storeQueue.end() &&
- (*sq_it).inst &&
- (*sq_it).canWB &&
- usedPorts < cachePorts) {
-
- DynInstPtr inst = (*sq_it).inst;
-
- if ((*sq_it).size == 0 && !(*sq_it).completed) {
- sq_it--;
- completeStore(inst->sqIdx);
-
- continue;
- }
-
- if (inst->isDataPrefetch() || (*sq_it).committed) {
- sq_it--;
- continue;
- }
-
- if (dcacheInterface && dcacheInterface->isBlocked()) {
- DPRINTF(OzoneLSQ, "Unable to write back any more stores, cache"
- " is blocked!\n");
- break;
- }
-
- ++usedPorts;
-
- assert((*sq_it).req);
- assert(!(*sq_it).committed);
-
- (*sq_it).committed = true;
-
- MemReqPtr req = (*sq_it).req;
-
- req->cmd = Write;
- req->completionEvent = NULL;
- req->time = curTick;
-
- switch((*sq_it).size) {
- case 1:
- cpu->write(req, (uint8_t &)(*sq_it).data);
- break;
- case 2:
- cpu->write(req, (uint16_t &)(*sq_it).data);
- break;
- case 4:
- cpu->write(req, (uint32_t &)(*sq_it).data);
- break;
- case 8:
- cpu->write(req, (uint64_t &)(*sq_it).data);
- break;
- default:
- panic("Unexpected store size!\n");
- }
- if (!(req->flags & LOCKED)) {
- (*sq_it).inst->setCompleted();
- if (cpu->checker) {
- cpu->checker->tick((*sq_it).inst);
- }
- }
-
- DPRINTF(OzoneLSQ, "D-Cache: Writing back store idx:%i PC:%#x "
- "to Addr:%#x, data:%#x [sn:%lli]\n",
- inst->sqIdx,inst->readPC(),
- req->paddr, *(req->data),
- inst->seqNum);
-
- if (dcacheInterface) {
- assert(!req->completionEvent);
- StoreCompletionEvent *store_event = new
- StoreCompletionEvent(inst, be, NULL, this);
- req->completionEvent = store_event;
-
- MemAccessResult result = dcacheInterface->access(req);
-
- if (isStalled() &&
- inst->seqNum == stallingStoreIsn) {
- DPRINTF(OzoneLSQ, "Unstalling, stalling store [sn:%lli] "
- "load [sn:%lli]\n",
- stallingStoreIsn, (*stallingLoad)->seqNum);
- stalled = false;
- stallingStoreIsn = 0;
- be->replayMemInst((*stallingLoad));
- }
-
- if (result != MA_HIT && dcacheInterface->doEvents()) {
- store_event->miss = true;
- typename BackEnd::LdWritebackEvent *wb = NULL;
- if (req->flags & LOCKED) {
- wb = new typename BackEnd::LdWritebackEvent(inst,
- be);
- store_event->wbEvent = wb;
- }
-
- DPRINTF(OzoneLSQ,"D-Cache Write Miss!\n");
-
-// DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n",
-// inst->seqNum);
-
- be->addDcacheMiss(inst);
-
- lastDcacheStall = curTick;
-
- _status = DcacheMissStall;
-
- // Increment stat here or something
-
- sq_it--;
- } else {
- DPRINTF(OzoneLSQ,"D-Cache: Write Hit on idx:%i !\n",
- inst->sqIdx);
-
-// DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
-// inst->seqNum);
-
- if (req->flags & LOCKED) {
- // Stx_C does not generate a system port
- // transaction in the 21264, but that might be
- // hard to accomplish in this model.
-
- typename BackEnd::LdWritebackEvent *wb =
- new typename BackEnd::LdWritebackEvent(inst,
- be);
- store_event->wbEvent = wb;
- }
- sq_it--;
- }
- } else {
- panic("Must HAVE DCACHE!!!!!\n");
- }
- }
-
- // Not sure this should set it to 0.
- usedPorts = 0;
-
- assert(stores >= 0 && storesToWB >= 0);
-}
-
-template <class Impl>
-void
-OzoneLWLSQ<Impl>::squash(const InstSeqNum &squashed_num)
-{
- DPRINTF(OzoneLSQ, "Squashing until [sn:%lli]!"
- "(Loads:%i Stores:%i)\n",squashed_num,loads,stores);
-
-
- LQIt lq_it = loadQueue.begin();
-
- while (loads != 0 && (*lq_it)->seqNum > squashed_num) {
- assert(!loadQueue.empty());
- // Clear the smart pointer to make sure it is decremented.
- DPRINTF(OzoneLSQ,"Load Instruction PC %#x squashed, "
- "[sn:%lli]\n",
- (*lq_it)->readPC(),
- (*lq_it)->seqNum);
-
- if (isStalled() && lq_it == stallingLoad) {
- stalled = false;
- stallingStoreIsn = 0;
- stallingLoad = NULL;
- }
-
- --loads;
-
- // Inefficient!
- LQHashIt lq_hash_it = LQItHash.find((*lq_it)->lqIdx);
- assert(lq_hash_it != LQItHash.end());
- LQItHash.erase(lq_hash_it);
- LQIndices.push((*lq_it)->lqIdx);
- loadQueue.erase(lq_it++);
- }
-
- if (isLoadBlocked) {
- if (squashed_num < blockedLoadSeqNum) {
- isLoadBlocked = false;
- loadBlockedHandled = false;
- blockedLoadSeqNum = 0;
- }
- }
-
- SQIt sq_it = storeQueue.begin();
-
- while (stores != 0 && (*sq_it).inst->seqNum > squashed_num) {
- assert(!storeQueue.empty());
-
- if ((*sq_it).canWB) {
- break;
- }
-
- // Clear the smart pointer to make sure it is decremented.
- DPRINTF(OzoneLSQ,"Store Instruction PC %#x idx:%i squashed [sn:%lli]\n",
- (*sq_it).inst->readPC(), (*sq_it).inst->sqIdx,
- (*sq_it).inst->seqNum);
-
- // I don't think this can happen. It should have been cleared by the
- // stalling load.
- if (isStalled() &&
- (*sq_it).inst->seqNum == stallingStoreIsn) {
- panic("Is stalled should have been cleared by stalling load!\n");
- stalled = false;
- stallingStoreIsn = 0;
- }
-
- SQHashIt sq_hash_it = SQItHash.find((*sq_it).inst->sqIdx);
- assert(sq_hash_it != SQItHash.end());
- SQItHash.erase(sq_hash_it);
- SQIndices.push((*sq_it).inst->sqIdx);
- (*sq_it).inst = NULL;
- (*sq_it).canWB = 0;
-
- if ((*sq_it).req) {
- assert(!(*sq_it).req->completionEvent);
- }
- (*sq_it).req = NULL;
- --stores;
- storeQueue.erase(sq_it++);
- }
-}
-
-template <class Impl>
-void
-OzoneLWLSQ<Impl>::dumpInsts()
-{
- cprintf("Load store queue: Dumping instructions.\n");
- cprintf("Load queue size: %i\n", loads);
- cprintf("Load queue: ");
-
- LQIt lq_it = --(loadQueue.end());
-
- while (lq_it != loadQueue.end() && (*lq_it)) {
- cprintf("[sn:%lli] %#x ", (*lq_it)->seqNum,
- (*lq_it)->readPC());
-
- lq_it--;
- }
-
- cprintf("\nStore queue size: %i\n", stores);
- cprintf("Store queue: ");
-
- SQIt sq_it = --(storeQueue.end());
-
- while (sq_it != storeQueue.end() && (*sq_it).inst) {
- cprintf("[sn:%lli]\nPC:%#x\nSize:%i\nCommitted:%i\nCompleted:%i\ncanWB:%i\n",
- (*sq_it).inst->seqNum,
- (*sq_it).inst->readPC(),
- (*sq_it).size,
- (*sq_it).committed,
- (*sq_it).completed,
- (*sq_it).canWB);
-
- sq_it--;
- }
-
- cprintf("\n");
-}
-
-template <class Impl>
-void
-OzoneLWLSQ<Impl>::completeStore(int store_idx)
-{
- SQHashIt sq_hash_it = SQItHash.find(store_idx);
- assert(sq_hash_it != SQItHash.end());
- SQIt sq_it = (*sq_hash_it).second;
-
- assert((*sq_it).inst);
- (*sq_it).completed = true;
- DynInstPtr inst = (*sq_it).inst;
-
- --storesToWB;
-
- if (isStalled() &&
- inst->seqNum == stallingStoreIsn) {
- DPRINTF(OzoneLSQ, "Unstalling, stalling store [sn:%lli] "
- "load [sn:%lli]\n",
- stallingStoreIsn, (*stallingLoad)->seqNum);
- stalled = false;
- stallingStoreIsn = 0;
- be->replayMemInst((*stallingLoad));
- }
-
- DPRINTF(OzoneLSQ, "Completing store idx:%i [sn:%lli], storesToWB:%i\n",
- inst->sqIdx, inst->seqNum, storesToWB);
-
- assert(!storeQueue.empty());
- SQItHash.erase(sq_hash_it);
- SQIndices.push(inst->sqIdx);
- storeQueue.erase(sq_it);
- --stores;
-
- inst->setCompleted();
- if (cpu->checker) {
- cpu->checker->tick(inst);
- }
-}
-
-template <class Impl>
-void
-OzoneLWLSQ<Impl>::switchOut()
-{
- assert(storesToWB == 0);
- switchedOut = true;
- SQIt sq_it = --(storeQueue.end());
- while (storesToWB > 0 &&
- sq_it != storeQueue.end() &&
- (*sq_it).inst &&
- (*sq_it).canWB) {
-
- DynInstPtr inst = (*sq_it).inst;
-
- if ((*sq_it).size == 0 && !(*sq_it).completed) {
- sq_it--;
- continue;
- }
-
- // Store conditionals don't complete until *after* they have written
- // back. If it's here and not yet sent to memory, then don't bother
- // as it's not part of committed state.
- if (inst->isDataPrefetch() || (*sq_it).committed) {
- sq_it--;
- continue;
- } else if ((*sq_it).req->flags & LOCKED) {
- sq_it--;
- assert(!(*sq_it).canWB ||
- ((*sq_it).canWB && (*sq_it).req->flags & LOCKED));
- continue;
- }
-
- assert((*sq_it).req);
- assert(!(*sq_it).committed);
-
- MemReqPtr req = (*sq_it).req;
- (*sq_it).committed = true;
-
- req->cmd = Write;
- req->completionEvent = NULL;
- req->time = curTick;
- assert(!req->data);
- req->data = new uint8_t[64];
- memcpy(req->data, (uint8_t *)&(*sq_it).data, req->size);
-
- DPRINTF(OzoneLSQ, "Switching out : Writing back store idx:%i PC:%#x "
- "to Addr:%#x, data:%#x directly to memory [sn:%lli]\n",
- inst->sqIdx,inst->readPC(),
- req->paddr, *(req->data),
- inst->seqNum);
-
- switch((*sq_it).size) {
- case 1:
- cpu->write(req, (uint8_t &)(*sq_it).data);
- break;
- case 2:
- cpu->write(req, (uint16_t &)(*sq_it).data);
- break;
- case 4:
- cpu->write(req, (uint32_t &)(*sq_it).data);
- break;
- case 8:
- cpu->write(req, (uint64_t &)(*sq_it).data);
- break;
- default:
- panic("Unexpected store size!\n");
- }
- }
-
- // Clear the queue to free up resources
- storeQueue.clear();
- loadQueue.clear();
- loads = stores = storesToWB = 0;
-}
-
-template <class Impl>
-void
-OzoneLWLSQ<Impl>::takeOverFrom(ExecContext *old_xc)
-{
- // Clear out any old state. May be redundant if this is the first time
- // the CPU is being used.
- stalled = false;
- isLoadBlocked = false;
- loadBlockedHandled = false;
- switchedOut = false;
-
- // Could do simple checks here to see if indices are on twice
- while (!LQIndices.empty())
- LQIndices.pop();
- while (!SQIndices.empty())
- SQIndices.pop();
-
- for (int i = 0; i < LQEntries * 2; i++) {
- LQIndices.push(i);
- SQIndices.push(i);
- }
-
- usedPorts = 0;
-
- loadFaultInst = storeFaultInst = memDepViolator = NULL;
-
- blockedLoadSeqNum = 0;
-}
diff --git a/cpu/ozone/null_predictor.hh b/cpu/ozone/null_predictor.hh
deleted file mode 100644
index d19e2cd1c..000000000
--- a/cpu/ozone/null_predictor.hh
+++ /dev/null
@@ -1,76 +0,0 @@
-
-#ifndef __CPU_OZONE_NULL_PREDICTOR_HH__
-#define __CPU_OZONE_NULL_PREDICTOR_HH__
-
-#include "arch/isa_traits.hh"
-#include "cpu/inst_seq.hh"
-
-template <class Impl>
-class NullPredictor
-{
- public:
- typedef typename Impl::Params Params;
- typedef typename Impl::DynInstPtr DynInstPtr;
-
- NullPredictor(Params *p) { }
-
- struct BPredInfo {
- BPredInfo()
- : PC(0), nextPC(0)
- { }
-
- BPredInfo(const Addr &pc, const Addr &next_pc)
- : PC(pc), nextPC(next_pc)
- { }
-
- Addr PC;
- Addr nextPC;
- };
-
- BPredInfo lookup(Addr &PC) { return BPredInfo(PC, PC+4); }
-
- void undo(BPredInfo &bp_info) { return; }
-
- /**
- * Predicts whether or not the instruction is a taken branch, and the
- * target of the branch if it is taken.
- * @param inst The branch instruction.
- * @param PC The predicted PC is passed back through this parameter.
- * @param tid The thread id.
- * @return Returns if the branch is taken or not.
- */
- bool predict(DynInstPtr &inst, Addr &PC, unsigned tid)
- { return false; }
-
- /**
- * Tells the branch predictor to commit any updates until the given
- * sequence number.
- * @param done_sn The sequence number to commit any older updates up until.
- * @param tid The thread id.
- */
- void update(const InstSeqNum &done_sn, unsigned tid) { }
-
- /**
- * Squashes all outstanding updates until a given sequence number.
- * @param squashed_sn The sequence number to squash any younger updates up
- * until.
- * @param tid The thread id.
- */
- void squash(const InstSeqNum &squashed_sn, unsigned tid) { }
-
- /**
- * Squashes all outstanding updates until a given sequence number, and
- * corrects that sn's update with the proper address and taken/not taken.
- * @param squashed_sn The sequence number to squash any younger updates up
- * until.
- * @param corr_target The correct branch target.
- * @param actually_taken The correct branch direction.
- * @param tid The thread id.
- */
- void squash(const InstSeqNum &squashed_sn, const Addr &corr_target,
- bool actually_taken, unsigned tid)
- { }
-
-};
-
-#endif // __CPU_OZONE_NULL_PREDICTOR_HH__
diff --git a/cpu/ozone/ozone_impl.hh b/cpu/ozone/ozone_impl.hh
deleted file mode 100644
index 9dc50c1fb..000000000
--- a/cpu/ozone/ozone_impl.hh
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_OZONE_OZONE_IMPL_HH__
-#define __CPU_OZONE_OZONE_IMPL_HH__
-
-#include "arch/alpha/isa_traits.hh"
-#include "cpu/o3/bpred_unit.hh"
-#include "cpu/ozone/back_end.hh"
-#include "cpu/ozone/front_end.hh"
-#include "cpu/ozone/inst_queue.hh"
-#include "cpu/ozone/lsq_unit.hh"
-#include "cpu/ozone/lw_lsq.hh"
-#include "cpu/ozone/lw_back_end.hh"
-#include "cpu/ozone/null_predictor.hh"
-#include "cpu/ozone/dyn_inst.hh"
-#include "cpu/ozone/simple_params.hh"
-
-template <class Impl>
-class OzoneCPU;
-
-template <class Impl>
-class OzoneDynInst;
-
-struct OzoneImpl {
- typedef SimpleParams Params;
- typedef OzoneCPU<OzoneImpl> OzoneCPU;
- typedef OzoneCPU FullCPU;
-
- // Would like to put these into their own area.
-// typedef NullPredictor BranchPred;
- typedef BPredUnit<OzoneImpl> BranchPred;
- typedef FrontEnd<OzoneImpl> FrontEnd;
- // Will need IQ, LSQ eventually
- typedef LWBackEnd<OzoneImpl> BackEnd;
-
- typedef InstQueue<OzoneImpl> InstQueue;
- typedef OzoneLWLSQ<OzoneImpl> LdstQueue;
-
- typedef OzoneDynInst<OzoneImpl> DynInst;
- typedef RefCountingPtr<DynInst> DynInstPtr;
-
- typedef uint64_t IssueStruct;
-
- enum {
- MaxThreads = 1
- };
-};
-
-#endif // __CPU_OZONE_OZONE_IMPL_HH__
diff --git a/cpu/ozone/rename_table.cc b/cpu/ozone/rename_table.cc
deleted file mode 100644
index fff41903e..000000000
--- a/cpu/ozone/rename_table.cc
+++ /dev/null
@@ -1,7 +0,0 @@
-
-#include "cpu/ozone/rename_table_impl.hh"
-#include "cpu/ozone/ozone_impl.hh"
-#include "cpu/ozone/simple_impl.hh"
-
-template class RenameTable<OzoneImpl>;
-template class RenameTable<SimpleImpl>;
diff --git a/cpu/ozone/rename_table.hh b/cpu/ozone/rename_table.hh
deleted file mode 100644
index 6ee23b21b..000000000
--- a/cpu/ozone/rename_table.hh
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_OZONE_RENAME_TABLE_HH__
-#define __CPU_OZONE_RENAME_TABLE_HH__
-
-#include "arch/isa_traits.hh"
-
-/** Rename table that holds the rename of each architectural register to
- * producing DynInst. Needs to support copying from one table to another.
- */
-
-template <class Impl>
-class RenameTable {
- public:
- typedef typename Impl::DynInstPtr DynInstPtr;
-
- RenameTable();
-
- void copyFrom(const RenameTable<Impl> &table_to_copy);
-
- DynInstPtr &operator [] (int index)
- { return table[index]; }
-
- DynInstPtr table[TheISA::TotalNumRegs];
-};
-
-#endif // __CPU_OZONE_RENAME_TABLE_HH__
diff --git a/cpu/ozone/rename_table_impl.hh b/cpu/ozone/rename_table_impl.hh
deleted file mode 100644
index 86fc1cc55..000000000
--- a/cpu/ozone/rename_table_impl.hh
+++ /dev/null
@@ -1,23 +0,0 @@
-
-#include <cstdlib> // Not really sure what to include to get NULL
-#include "cpu/ozone/rename_table.hh"
-
-template <class Impl>
-RenameTable<Impl>::RenameTable()
-{
- // Actually should set these to dummy dyn insts that have the initial value
- // and force their values to be initialized. This keeps everything the
- // same.
- for (int i = 0; i < TheISA::TotalNumRegs; ++i) {
- table[i] = NULL;
- }
-}
-
-template <class Impl>
-void
-RenameTable<Impl>::copyFrom(const RenameTable<Impl> &table_to_copy)
-{
- for (int i = 0; i < TheISA::TotalNumRegs; ++i) {
- table[i] = table_to_copy.table[i];
- }
-}
diff --git a/cpu/ozone/simple_impl.hh b/cpu/ozone/simple_impl.hh
deleted file mode 100644
index 26845271a..000000000
--- a/cpu/ozone/simple_impl.hh
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_OZONE_SIMPLE_IMPL_HH__
-#define __CPU_OZONE_SIMPLE_IMPL_HH__
-
-#include "arch/isa_traits.hh"
-#include "cpu/o3/bpred_unit.hh"
-#include "cpu/ozone/cpu.hh"
-#include "cpu/ozone/front_end.hh"
-#include "cpu/ozone/inorder_back_end.hh"
-#include "cpu/ozone/null_predictor.hh"
-#include "cpu/ozone/dyn_inst.hh"
-#include "cpu/ozone/simple_params.hh"
-
-//template <class Impl>
-//class OzoneCPU;
-
-template <class Impl>
-class OzoneDynInst;
-
-struct SimpleImpl {
- typedef SimpleParams Params;
- typedef OzoneCPU<SimpleImpl> OzoneCPU;
- typedef OzoneCPU FullCPU;
-
- // Would like to put these into their own area.
-// typedef NullPredictor BranchPred;
- typedef BPredUnit<SimpleImpl> BranchPred;
- typedef FrontEnd<SimpleImpl> FrontEnd;
- // Will need IQ, LSQ eventually
- typedef InorderBackEnd<SimpleImpl> BackEnd;
-
- typedef OzoneDynInst<SimpleImpl> DynInst;
- typedef RefCountingPtr<DynInst> DynInstPtr;
-
- typedef uint64_t IssueStruct;
-
- enum {
- MaxThreads = 1
- };
-};
-
-#endif // __CPU_OZONE_SIMPLE_IMPL_HH__
diff --git a/cpu/ozone/simple_params.hh b/cpu/ozone/simple_params.hh
deleted file mode 100644
index 7b5c6f67b..000000000
--- a/cpu/ozone/simple_params.hh
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_OZONE_SIMPLE_PARAMS_HH__
-#define __CPU_OZONE_SIMPLE_PARAMS_HH__
-
-#include "cpu/ozone/cpu.hh"
-
-//Forward declarations
-class AlphaDTB;
-class AlphaITB;
-class FUPool;
-class FunctionalMemory;
-class MemInterface;
-class PageTable;
-class Process;
-class System;
-
-/**
- * This file defines the parameters that will be used for the OzoneCPU.
- * This must be defined externally so that the Impl can have a params class
- * defined that it can pass to all of the individual stages.
- */
-
-class SimpleParams : public BaseCPU::Params
-{
- public:
-
-#if FULL_SYSTEM
- AlphaITB *itb; AlphaDTB *dtb;
-#else
- std::vector<Process *> workload;
-#endif // FULL_SYSTEM
-
- //Page Table
- PageTable *pTable;
-
- FunctionalMemory *mem;
-
- //
- // Caches
- //
- MemInterface *icacheInterface;
- MemInterface *dcacheInterface;
-
- unsigned cachePorts;
- unsigned width;
- unsigned frontEndWidth;
- unsigned backEndWidth;
- unsigned backEndSquashLatency;
- unsigned backEndLatency;
- unsigned maxInstBufferSize;
- unsigned numPhysicalRegs;
- unsigned maxOutstandingMemOps;
- //
- // Fetch
- //
- unsigned decodeToFetchDelay;
- unsigned renameToFetchDelay;
- unsigned iewToFetchDelay;
- unsigned commitToFetchDelay;
- unsigned fetchWidth;
-
- //
- // Decode
- //
- unsigned renameToDecodeDelay;
- unsigned iewToDecodeDelay;
- unsigned commitToDecodeDelay;
- unsigned fetchToDecodeDelay;
- unsigned decodeWidth;
-
- //
- // Rename
- //
- unsigned iewToRenameDelay;
- unsigned commitToRenameDelay;
- unsigned decodeToRenameDelay;
- unsigned renameWidth;
-
- //
- // IEW
- //
- unsigned commitToIEWDelay;
- unsigned renameToIEWDelay;
- unsigned issueToExecuteDelay;
- unsigned issueWidth;
- unsigned executeWidth;
- unsigned executeIntWidth;
- unsigned executeFloatWidth;
- unsigned executeBranchWidth;
- unsigned executeMemoryWidth;
- FUPool *fuPool;
-
- //
- // Commit
- //
- unsigned iewToCommitDelay;
- unsigned renameToROBDelay;
- unsigned commitWidth;
- unsigned squashWidth;
-
- //
- // Branch predictor (BP & BTB)
- //
- std::string predType;
- unsigned localPredictorSize;
- unsigned localCtrBits;
- unsigned localHistoryTableSize;
- unsigned localHistoryBits;
- unsigned globalPredictorSize;
- unsigned globalCtrBits;
- unsigned globalHistoryBits;
- unsigned choicePredictorSize;
- unsigned choiceCtrBits;
-
- unsigned BTBEntries;
- unsigned BTBTagSize;
-
- unsigned RASSize;
-
- //
- // Load store queue
- //
- unsigned LQEntries;
- unsigned SQEntries;
-
- //
- // Memory dependence
- //
- unsigned SSITSize;
- unsigned LFSTSize;
-
- //
- // Miscellaneous
- //
- unsigned numPhysIntRegs;
- unsigned numPhysFloatRegs;
- unsigned numIQEntries;
- unsigned numROBEntries;
-
- bool decoupledFrontEnd;
- int dispatchWidth;
- int wbWidth;
-
- //SMT Parameters
- unsigned smtNumFetchingThreads;
-
- std::string smtFetchPolicy;
-
- std::string smtIQPolicy;
- unsigned smtIQThreshold;
-
- std::string smtLSQPolicy;
- unsigned smtLSQThreshold;
-
- std::string smtCommitPolicy;
-
- std::string smtROBPolicy;
- unsigned smtROBThreshold;
-
- // Probably can get this from somewhere.
- unsigned instShiftAmt;
-};
-
-#endif // __CPU_OZONE_SIMPLE_PARAMS_HH__
diff --git a/cpu/ozone/thread_state.hh b/cpu/ozone/thread_state.hh
deleted file mode 100644
index c86c3a720..000000000
--- a/cpu/ozone/thread_state.hh
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_OZONE_THREAD_STATE_HH__
-#define __CPU_OZONE_THREAD_STATE_HH__
-
-#include "arch/faults.hh"
-#include "arch/isa_traits.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/thread_state.hh"
-#include "sim/process.hh"
-
-class Event;
-//class Process;
-
-#if FULL_SYSTEM
-class EndQuiesceEvent;
-class FunctionProfile;
-class ProfileNode;
-#else
-class Process;
-class FunctionalMemory;
-#endif
-
-// Maybe this ozone thread state should only really have committed state?
-// I need to think about why I'm using this and what it's useful for. Clearly
-// has benefits for SMT; basically serves same use as CPUExecContext.
-// Makes the ExecContext proxy easier. Gives organization/central access point
-// to state of a thread that can be accessed normally (i.e. not in-flight
-// stuff within a OoO processor). Does this need an XC proxy within it?
-template <class Impl>
-struct OzoneThreadState : public ThreadState {
- typedef typename ExecContext::Status Status;
- typedef typename Impl::FullCPU FullCPU;
- typedef TheISA::MiscReg MiscReg;
-
-#if FULL_SYSTEM
- OzoneThreadState(FullCPU *_cpu, int _thread_num, FunctionalMemory *_mem)
- : ThreadState(-1, _thread_num, _mem),
- inSyscall(0), trapPending(0)
- {
- memset(&regs, 0, sizeof(TheISA::RegFile));
- }
-#else
- OzoneThreadState(FullCPU *_cpu, int _thread_num, Process *_process, int _asid)
- : ThreadState(-1, _thread_num, _process->getMemory(), _process, _asid),
- cpu(_cpu), inSyscall(0), trapPending(0)
- {
- memset(&regs, 0, sizeof(TheISA::RegFile));
- }
-
- OzoneThreadState(FullCPU *_cpu, int _thread_num, FunctionalMemory *_mem,
- int _asid)
- : ThreadState(-1, _thread_num, _mem, NULL, _asid),
- cpu(_cpu), inSyscall(0), trapPending(0)
- {
- memset(&regs, 0, sizeof(TheISA::RegFile));
- }
-#endif
-
- Status _status;
-
- Status status() const { return _status; }
-
- void setStatus(Status new_status) { _status = new_status; }
-
- RenameTable<Impl> renameTable;
- Addr PC;
- Addr nextPC;
-
- // Current instruction
- TheISA::MachInst inst;
-
- TheISA::RegFile regs;
-
- typename Impl::FullCPU *cpu;
-
- bool inSyscall;
-
- bool trapPending;
-
- ExecContext *xcProxy;
-
- ExecContext *getXCProxy() { return xcProxy; }
-
-#if !FULL_SYSTEM
-
- Fault dummyTranslation(MemReqPtr &req)
- {
-#if 0
- assert((req->vaddr >> 48 & 0xffff) == 0);
-#endif
-
- // put the asid in the upper 16 bits of the paddr
- req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
- req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
- return NoFault;
- }
- Fault translateInstReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
- Fault translateDataReadReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
- Fault translateDataWriteReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
-#else
- Fault translateInstReq(MemReqPtr &req)
- {
- return cpu->itb->translate(req);
- }
-
- Fault translateDataReadReq(MemReqPtr &req)
- {
- return cpu->dtb->translate(req, false);
- }
-
- Fault translateDataWriteReq(MemReqPtr &req)
- {
- return cpu->dtb->translate(req, true);
- }
-#endif
-
- MiscReg readMiscReg(int misc_reg)
- {
- return regs.miscRegs.readReg(misc_reg);
- }
-
- MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
- {
- return regs.miscRegs.readRegWithEffect(misc_reg, fault, xcProxy);
- }
-
- Fault setMiscReg(int misc_reg, const MiscReg &val)
- {
- return regs.miscRegs.setReg(misc_reg, val);
- }
-
- Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
- {
- return regs.miscRegs.setRegWithEffect(misc_reg, val, xcProxy);
- }
-
- uint64_t readPC()
- { return PC; }
-
- void setPC(uint64_t val)
- { PC = val; }
-
- uint64_t readNextPC()
- { return nextPC; }
-
- void setNextPC(uint64_t val)
- { nextPC = val; }
-
- bool misspeculating() { return false; }
-
- void setInst(TheISA::MachInst _inst) { inst = _inst; }
-
- Counter readFuncExeInst() { return funcExeInst; }
-
- void setFuncExeInst(Counter new_val) { funcExeInst = new_val; }
-};
-
-#endif // __CPU_OZONE_THREAD_STATE_HH__
diff --git a/cpu/pc_event.cc b/cpu/pc_event.cc
deleted file mode 100644
index 050bf1a88..000000000
--- a/cpu/pc_event.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <algorithm>
-#include <map>
-#include <string>
-#include <utility>
-
-#include "base/trace.hh"
-#include "config/full_system.hh"
-#include "cpu/base.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/pc_event.hh"
-#include "sim/debug.hh"
-#include "sim/root.hh"
-#include "sim/system.hh"
-
-using namespace std;
-
-PCEventQueue::PCEventQueue()
-{}
-
-PCEventQueue::~PCEventQueue()
-{}
-
-bool
-PCEventQueue::remove(PCEvent *event)
-{
- int removed = 0;
- range_t range = equal_range(event);
- for (iterator i = range.first; i != range.second; ++i) {
- if (*i == event) {
- DPRINTF(PCEvent, "PC based event removed at %#x: %s\n",
- event->pc(), event->descr());
- pc_map.erase(i);
- ++removed;
- }
- }
-
- return removed > 0;
-}
-
-bool
-PCEventQueue::schedule(PCEvent *event)
-{
- pc_map.push_back(event);
- sort(pc_map.begin(), pc_map.end(), MapCompare());
-
- DPRINTF(PCEvent, "PC based event scheduled for %#x: %s\n",
- event->pc(), event->descr());
-
- return true;
-}
-
-bool
-PCEventQueue::doService(ExecContext *xc)
-{
- Addr pc = xc->readPC() & ~0x3;
- int serviced = 0;
- range_t range = equal_range(pc);
- for (iterator i = range.first; i != range.second; ++i) {
- // Make sure that the pc wasn't changed as the side effect of
- // another event. This for example, prevents two invocations
- // of the SkipFuncEvent. Maybe we should have separate PC
- // event queues for each processor?
- if (pc != (xc->readPC() & ~0x3))
- continue;
-
- DPRINTF(PCEvent, "PC based event serviced at %#x: %s\n",
- (*i)->pc(), (*i)->descr());
-
- (*i)->process(xc);
- ++serviced;
- }
-
- return serviced > 0;
-}
-
-void
-PCEventQueue::dump() const
-{
- const_iterator i = pc_map.begin();
- const_iterator e = pc_map.end();
-
- for (; i != e; ++i)
- cprintf("%d: event at %#x: %s\n", curTick, (*i)->pc(),
- (*i)->descr());
-}
-
-PCEventQueue::range_t
-PCEventQueue::equal_range(Addr pc)
-{
- return std::equal_range(pc_map.begin(), pc_map.end(), pc, MapCompare());
-}
-
-BreakPCEvent::BreakPCEvent(PCEventQueue *q, const std::string &desc, Addr addr,
- bool del)
- : PCEvent(q, desc, addr), remove(del)
-{
-}
-
-void
-BreakPCEvent::process(ExecContext *xc)
-{
- StringWrap name(xc->getCpuPtr()->name() + ".break_event");
- DPRINTFN("break event %s triggered\n", descr());
- debug_break();
- if (remove)
- delete this;
-}
-
-#if FULL_SYSTEM
-extern "C"
-void
-sched_break_pc_sys(System *sys, Addr addr)
-{
- new BreakPCEvent(&sys->pcEventQueue, "debug break", addr, true);
-}
-
-extern "C"
-void
-sched_break_pc(Addr addr)
-{
- for (vector<System *>::iterator sysi = System::systemList.begin();
- sysi != System::systemList.end(); ++sysi) {
- sched_break_pc_sys(*sysi, addr);
- }
-
-}
-#endif
diff --git a/cpu/pc_event.hh b/cpu/pc_event.hh
deleted file mode 100644
index 7fa3902cc..000000000
--- a/cpu/pc_event.hh
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __PC_EVENT_HH__
-#define __PC_EVENT_HH__
-
-#include <vector>
-
-#include "mem/mem_req.hh"
-
-class ExecContext;
-class PCEventQueue;
-
-class PCEvent
-{
- protected:
- static const Addr badpc = MemReq::inval_addr;
-
- protected:
- std::string description;
- PCEventQueue *queue;
- Addr evpc;
-
- public:
- PCEvent(PCEventQueue *q, const std::string &desc, Addr pc);
-
- virtual ~PCEvent() { if (queue) remove(); }
-
- // for DPRINTF
- virtual const std::string name() const { return description; }
-
- std::string descr() const { return description; }
- Addr pc() const { return evpc; }
-
- bool remove();
- virtual void process(ExecContext *xc) = 0;
-};
-
-class PCEventQueue
-{
- protected:
- typedef PCEvent * record_t;
- class MapCompare {
- public:
- bool operator()(const record_t &l, const record_t &r) const {
- return l->pc() < r->pc();
- }
- bool operator()(const record_t &l, Addr pc) const {
- return l->pc() < pc;
- }
- bool operator()(Addr pc, const record_t &r) const {
- return pc < r->pc();
- }
- };
- typedef std::vector<record_t> map_t;
-
- public:
- typedef map_t::iterator iterator;
- typedef map_t::const_iterator const_iterator;
-
- protected:
- typedef std::pair<iterator, iterator> range_t;
- typedef std::pair<const_iterator, const_iterator> const_range_t;
-
- protected:
- map_t pc_map;
-
- bool doService(ExecContext *xc);
-
- public:
- PCEventQueue();
- ~PCEventQueue();
-
- bool remove(PCEvent *event);
- bool schedule(PCEvent *event);
- bool service(ExecContext *xc)
- {
- if (pc_map.empty())
- return false;
-
- return doService(xc);
- }
-
- range_t equal_range(Addr pc);
- range_t equal_range(PCEvent *event) { return equal_range(event->pc()); }
-
- void dump() const;
-};
-
-
-inline
-PCEvent::PCEvent(PCEventQueue *q, const std::string &desc, Addr pc)
- : description(desc), queue(q), evpc(pc)
-{
- queue->schedule(this);
-}
-
-inline bool
-PCEvent::remove()
-{
- if (!queue)
- panic("cannot remove an uninitialized event;");
-
- return queue->remove(this);
-}
-
-class BreakPCEvent : public PCEvent
-{
- protected:
- bool remove;
-
- public:
- BreakPCEvent(PCEventQueue *q, const std::string &desc, Addr addr,
- bool del = false);
- virtual void process(ExecContext *xc);
-};
-
-#endif // __PC_EVENT_HH__
diff --git a/cpu/profile.cc b/cpu/profile.cc
deleted file mode 100644
index fe3458b61..000000000
--- a/cpu/profile.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (c) 2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <string>
-
-#include "base/bitfield.hh"
-#include "base/callback.hh"
-#include "base/statistics.hh"
-#include "base/trace.hh"
-#include "base/loader/symtab.hh"
-#include "cpu/base.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/profile.hh"
-
-using namespace std;
-
-ProfileNode::ProfileNode()
- : count(0)
-{ }
-
-void
-ProfileNode::dump(const string &symbol, uint64_t id, const SymbolTable *symtab,
- ostream &os) const
-{
- ccprintf(os, "%#x %s %d ", id, symbol, count);
- ChildList::const_iterator i, end = children.end();
- for (i = children.begin(); i != end; ++i) {
- const ProfileNode *node = i->second;
- ccprintf(os, "%#x ", (intptr_t)node);
- }
-
- ccprintf(os, "\n");
-
- for (i = children.begin(); i != end; ++i) {
- Addr addr = i->first;
- string symbol;
- if (addr == 1)
- symbol = "user";
- else if (addr == 2)
- symbol = "console";
- else if (addr == 3)
- symbol = "unknown";
- else if (!symtab->findSymbol(addr, symbol))
- panic("could not find symbol for address %#x\n", addr);
-
- const ProfileNode *node = i->second;
- node->dump(symbol, (intptr_t)node, symtab, os);
- }
-}
-
-void
-ProfileNode::clear()
-{
- count = 0;
- ChildList::iterator i, end = children.end();
- for (i = children.begin(); i != end; ++i)
- i->second->clear();
-}
-
-FunctionProfile::FunctionProfile(const SymbolTable *_symtab)
- : reset(0), symtab(_symtab)
-{
- reset = new MakeCallback<FunctionProfile, &FunctionProfile::clear>(this);
- Stats::registerResetCallback(reset);
-}
-
-FunctionProfile::~FunctionProfile()
-{
- if (reset)
- delete reset;
-}
-
-ProfileNode *
-FunctionProfile::consume(const vector<Addr> &stack)
-{
- ProfileNode *current = &top;
- for (int i = 0, size = stack.size(); i < size; ++i) {
- ProfileNode *&ptr = current->children[stack[size - i - 1]];
- if (ptr == NULL)
- ptr = new ProfileNode;
-
- current = ptr;
- }
-
- return current;
-}
-
-void
-FunctionProfile::clear()
-{
- top.clear();
- pc_count.clear();
-}
-
-void
-FunctionProfile::dump(ExecContext *xc, ostream &os) const
-{
- ccprintf(os, ">>>PC data\n");
- map<Addr, Counter>::const_iterator i, end = pc_count.end();
- for (i = pc_count.begin(); i != end; ++i) {
- Addr pc = i->first;
- Counter count = i->second;
-
- std::string symbol;
- if (pc == 1)
- ccprintf(os, "user %d\n", count);
- else if (symtab->findSymbol(pc, symbol) && !symbol.empty())
- ccprintf(os, "%s %d\n", symbol, count);
- else
- ccprintf(os, "%#x %d\n", pc, count);
- }
-
- ccprintf(os, ">>>function data\n");
- top.dump("top", 0, symtab, os);
-}
-
-void
-FunctionProfile::sample(ProfileNode *node, Addr pc)
-{
- node->count++;
-
- Addr symaddr;
- if (symtab->findNearestAddr(pc, symaddr)) {
- pc_count[symaddr]++;
- } else {
- // record PC even if we don't have a symbol to avoid
- // silently biasing the histogram
- pc_count[pc]++;
- }
-}
diff --git a/cpu/profile.hh b/cpu/profile.hh
deleted file mode 100644
index d55c9eec9..000000000
--- a/cpu/profile.hh
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_PROFILE_HH__
-#define __CPU_PROFILE_HH__
-
-#include <map>
-
-#include "cpu/static_inst.hh"
-#include "sim/host.hh"
-#include "arch/stacktrace.hh"
-
-class ExecContext;
-
-class ProfileNode
-{
- private:
- friend class FunctionProfile;
-
- typedef std::map<Addr, ProfileNode *> ChildList;
- ChildList children;
-
- public:
- Counter count;
-
- public:
- ProfileNode();
-
- void dump(const std::string &symbol, uint64_t id,
- const SymbolTable *symtab, std::ostream &os) const;
- void clear();
-};
-
-class Callback;
-class FunctionProfile
-{
- private:
- Callback *reset;
- const SymbolTable *symtab;
- ProfileNode top;
- std::map<Addr, Counter> pc_count;
- StackTrace trace;
-
- public:
- FunctionProfile(const SymbolTable *symtab);
- ~FunctionProfile();
-
- ProfileNode *consume(ExecContext *xc, StaticInstPtr inst);
- ProfileNode *consume(const std::vector<Addr> &stack);
- void clear();
- void dump(ExecContext *xc, std::ostream &out) const;
- void sample(ProfileNode *node, Addr pc);
-};
-
-inline ProfileNode *
-FunctionProfile::consume(ExecContext *xc, StaticInstPtr inst)
-{
- if (!trace.trace(xc, inst))
- return NULL;
- trace.dprintf();
- return consume(trace.getstack());
-}
-
-#endif // __CPU_PROFILE_HH__
diff --git a/cpu/quiesce_event.cc b/cpu/quiesce_event.cc
deleted file mode 100644
index 37814ae09..000000000
--- a/cpu/quiesce_event.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-
-#include "cpu/exec_context.hh"
-#include "cpu/quiesce_event.hh"
-
-EndQuiesceEvent::EndQuiesceEvent(ExecContext *_xc)
- : Event(&mainEventQueue), xc(_xc)
-{
-}
-
-void
-EndQuiesceEvent::process()
-{
- xc->activate();
-}
-
-const char*
-EndQuiesceEvent::description()
-{
- return "End Quiesce Event.";
-}
diff --git a/cpu/quiesce_event.hh b/cpu/quiesce_event.hh
deleted file mode 100644
index 18e88ecce..000000000
--- a/cpu/quiesce_event.hh
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef __CPU_QUIESCE_EVENT_HH__
-#define __CPU_QUIESCE_EVENT_HH__
-
-#include "sim/eventq.hh"
-
-class ExecContext;
-
-/** Event for timing out quiesce instruction */
-struct EndQuiesceEvent : public Event
-{
- /** A pointer to the execution context that is quiesced */
- ExecContext *xc;
-
- EndQuiesceEvent(ExecContext *_xc);
-
- /** Event process to occur at interrupt*/
- virtual void process();
-
- /** Event description */
- virtual const char *description();
-};
-
-#endif // __CPU_QUIESCE_EVENT_HH__
diff --git a/cpu/simple/cpu.cc b/cpu/simple/cpu.cc
deleted file mode 100644
index c03945ffa..000000000
--- a/cpu/simple/cpu.cc
+++ /dev/null
@@ -1,955 +0,0 @@
-/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <cmath>
-#include <cstdio>
-#include <cstdlib>
-#include <iostream>
-#include <iomanip>
-#include <list>
-#include <sstream>
-#include <string>
-
-#include "base/cprintf.hh"
-#include "base/inifile.hh"
-#include "base/loader/symtab.hh"
-#include "base/misc.hh"
-#include "base/pollevent.hh"
-#include "base/range.hh"
-#include "base/stats/events.hh"
-#include "base/trace.hh"
-#include "cpu/base.hh"
-#include "cpu/cpu_exec_context.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/exetrace.hh"
-#include "cpu/profile.hh"
-#include "cpu/sampler/sampler.hh"
-#include "cpu/simple/cpu.hh"
-#include "cpu/smt.hh"
-#include "cpu/static_inst.hh"
-#include "kern/kernel_stats.hh"
-#include "mem/base_mem.hh"
-#include "mem/mem_interface.hh"
-#include "sim/byteswap.hh"
-#include "sim/builder.hh"
-#include "sim/debug.hh"
-#include "sim/host.hh"
-#include "sim/sim_events.hh"
-#include "sim/sim_object.hh"
-#include "sim/stats.hh"
-
-#if FULL_SYSTEM
-#include "base/remote_gdb.hh"
-#include "mem/functional/memory_control.hh"
-#include "mem/functional/physical.hh"
-#include "sim/system.hh"
-#include "arch/tlb.hh"
-#include "arch/stacktrace.hh"
-#include "arch/vtophys.hh"
-#else // !FULL_SYSTEM
-#include "mem/functional/functional.hh"
-#endif // FULL_SYSTEM
-
-using namespace std;
-//The SimpleCPU does alpha only
-using namespace AlphaISA;
-
-
-SimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w)
- : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c), width(w)
-{
-}
-
-
-void
-SimpleCPU::init()
-{
- BaseCPU::init();
-#if FULL_SYSTEM
- for (int i = 0; i < execContexts.size(); ++i) {
- ExecContext *xc = execContexts[i];
-
- // initialize CPU, including PC
- TheISA::initCPU(xc, xc->readCpuId());
- }
-#endif
-}
-
-void
-SimpleCPU::TickEvent::process()
-{
- int count = width;
- do {
- cpu->tick();
- } while (--count > 0 && cpu->status() == Running);
-}
-
-const char *
-SimpleCPU::TickEvent::description()
-{
- return "SimpleCPU tick event";
-}
-
-
-SimpleCPU::CacheCompletionEvent::CacheCompletionEvent(SimpleCPU *_cpu)
- : Event(&mainEventQueue), cpu(_cpu)
-{
-}
-
-void SimpleCPU::CacheCompletionEvent::process()
-{
- cpu->processCacheCompletion();
-}
-
-const char *
-SimpleCPU::CacheCompletionEvent::description()
-{
- return "SimpleCPU cache completion event";
-}
-
-SimpleCPU::SimpleCPU(Params *p)
- : BaseCPU(p), tickEvent(this, p->width), cpuXC(NULL),
- cacheCompletionEvent(this)
-{
- _status = Idle;
-#if FULL_SYSTEM
- cpuXC = new CPUExecContext(this, 0, p->system, p->itb, p->dtb, p->mem);
-
-#else
- cpuXC = new CPUExecContext(this, /* thread_num */ 0, p->process,
- /* asid */ 0);
-#endif // !FULL_SYSTEM
- cpuXC->setStatus(ExecContext::Suspended);
- xcProxy = cpuXC->getProxy();
-
- icacheInterface = p->icache_interface;
- dcacheInterface = p->dcache_interface;
-
- memReq = new MemReq();
- memReq->xc = xcProxy;
- memReq->asid = 0;
- memReq->data = new uint8_t[64];
-
- numInst = 0;
- startNumInst = 0;
- numLoad = 0;
- startNumLoad = 0;
- lastIcacheStall = 0;
- lastDcacheStall = 0;
-
- execContexts.push_back(xcProxy);
-}
-
-SimpleCPU::~SimpleCPU()
-{
-}
-
-void
-SimpleCPU::switchOut(Sampler *s)
-{
- sampler = s;
- if (status() == DcacheMissStall) {
- DPRINTF(Sampler,"Outstanding dcache access, waiting for completion\n");
- _status = DcacheMissSwitch;
- }
- else {
- _status = SwitchedOut;
-
- if (tickEvent.scheduled())
- tickEvent.squash();
-
- sampler->signalSwitched();
- }
-}
-
-
-void
-SimpleCPU::takeOverFrom(BaseCPU *oldCPU)
-{
- BaseCPU::takeOverFrom(oldCPU);
-
- assert(!tickEvent.scheduled());
-
- // if any of this CPU's ExecContexts are active, mark the CPU as
- // running and schedule its tick event.
- for (int i = 0; i < execContexts.size(); ++i) {
- ExecContext *xc = execContexts[i];
- if (xc->status() == ExecContext::Active && _status != Running) {
- _status = Running;
- tickEvent.schedule(curTick);
- }
- }
-}
-
-
-void
-SimpleCPU::activateContext(int thread_num, int delay)
-{
- assert(thread_num == 0);
- assert(cpuXC);
-
- assert(_status == Idle || _status == SwitchedOut);
- notIdleFraction++;
- scheduleTickEvent(delay);
- _status = Running;
-}
-
-
-void
-SimpleCPU::suspendContext(int thread_num)
-{
- assert(thread_num == 0);
- assert(cpuXC);
-
- assert(_status == Running || _status == SwitchedOut);
- notIdleFraction--;
- unscheduleTickEvent();
- _status = Idle;
-}
-
-
-void
-SimpleCPU::deallocateContext(int thread_num)
-{
- // for now, these are equivalent
- suspendContext(thread_num);
-}
-
-
-void
-SimpleCPU::haltContext(int thread_num)
-{
- // for now, these are equivalent
- suspendContext(thread_num);
-}
-
-
-void
-SimpleCPU::regStats()
-{
- using namespace Stats;
-
- BaseCPU::regStats();
-
- numInsts
- .name(name() + ".num_insts")
- .desc("Number of instructions executed")
- ;
-
- numMemRefs
- .name(name() + ".num_refs")
- .desc("Number of memory references")
- ;
-
- notIdleFraction
- .name(name() + ".not_idle_fraction")
- .desc("Percentage of non-idle cycles")
- ;
-
- idleFraction
- .name(name() + ".idle_fraction")
- .desc("Percentage of idle cycles")
- ;
-
- icacheStallCycles
- .name(name() + ".icache_stall_cycles")
- .desc("ICache total stall cycles")
- .prereq(icacheStallCycles)
- ;
-
- dcacheStallCycles
- .name(name() + ".dcache_stall_cycles")
- .desc("DCache total stall cycles")
- .prereq(dcacheStallCycles)
- ;
-
- idleFraction = constant(1.0) - notIdleFraction;
-}
-
-void
-SimpleCPU::resetStats()
-{
- startNumInst = numInst;
- notIdleFraction = (_status != Idle);
-}
-
-void
-SimpleCPU::serialize(ostream &os)
-{
- BaseCPU::serialize(os);
- SERIALIZE_ENUM(_status);
- SERIALIZE_SCALAR(inst);
- nameOut(os, csprintf("%s.xc", name()));
- cpuXC->serialize(os);
- nameOut(os, csprintf("%s.tickEvent", name()));
- tickEvent.serialize(os);
- nameOut(os, csprintf("%s.cacheCompletionEvent", name()));
- cacheCompletionEvent.serialize(os);
-}
-
-void
-SimpleCPU::unserialize(Checkpoint *cp, const string &section)
-{
- BaseCPU::unserialize(cp, section);
- UNSERIALIZE_ENUM(_status);
- UNSERIALIZE_SCALAR(inst);
- cpuXC->unserialize(cp, csprintf("%s.xc", section));
- tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
- cacheCompletionEvent
- .unserialize(cp, csprintf("%s.cacheCompletionEvent", section));
-}
-
-void
-change_thread_state(int thread_number, int activate, int priority)
-{
-}
-
-Fault
-SimpleCPU::copySrcTranslate(Addr src)
-{
- static bool no_warn = true;
- int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
- // Only support block sizes of 64 atm.
- assert(blk_size == 64);
- int offset = src & (blk_size - 1);
-
- // Make sure block doesn't span page
- if (no_warn &&
- (src & PageMask) != ((src + blk_size) & PageMask) &&
- (src >> 40) != 0xfffffc) {
- warn("Copied block source spans pages %x.", src);
- no_warn = false;
- }
-
- memReq->reset(src & ~(blk_size - 1), blk_size);
-
- // translate to physical address
- Fault fault = cpuXC->translateDataReadReq(memReq);
-
- if (fault == NoFault) {
- cpuXC->copySrcAddr = src;
- cpuXC->copySrcPhysAddr = memReq->paddr + offset;
- } else {
- assert(!fault->isAlignmentFault());
-
- cpuXC->copySrcAddr = 0;
- cpuXC->copySrcPhysAddr = 0;
- }
- return fault;
-}
-
-Fault
-SimpleCPU::copy(Addr dest)
-{
- static bool no_warn = true;
- int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
- // Only support block sizes of 64 atm.
- assert(blk_size == 64);
- uint8_t data[blk_size];
- //assert(cpuXC->copySrcAddr);
- int offset = dest & (blk_size - 1);
-
- // Make sure block doesn't span page
- if (no_warn &&
- (dest & PageMask) != ((dest + blk_size) & PageMask) &&
- (dest >> 40) != 0xfffffc) {
- no_warn = false;
- warn("Copied block destination spans pages %x. ", dest);
- }
-
- memReq->reset(dest & ~(blk_size -1), blk_size);
- // translate to physical address
- Fault fault = cpuXC->translateDataWriteReq(memReq);
-
- if (fault == NoFault) {
- Addr dest_addr = memReq->paddr + offset;
- // Need to read straight from memory since we have more than 8 bytes.
- memReq->paddr = cpuXC->copySrcPhysAddr;
- cpuXC->mem->read(memReq, data);
- memReq->paddr = dest_addr;
- cpuXC->mem->write(memReq, data);
- if (dcacheInterface) {
- memReq->cmd = Copy;
- memReq->completionEvent = NULL;
- memReq->paddr = cpuXC->copySrcPhysAddr;
- memReq->dest = dest_addr;
- memReq->size = 64;
- memReq->time = curTick;
- memReq->flags &= ~INST_READ;
- dcacheInterface->access(memReq);
- }
- }
- else
- assert(!fault->isAlignmentFault());
-
- return fault;
-}
-
-// precise architected memory state accessor macros
-template <class T>
-Fault
-SimpleCPU::read(Addr addr, T &data, unsigned flags)
-{
- if (status() == DcacheMissStall || status() == DcacheMissSwitch) {
- Fault fault = cpuXC->read(memReq,data);
-
- if (traceData) {
- traceData->setAddr(memReq->vaddr);
- }
- return fault;
- }
-
- memReq->reset(addr, sizeof(T), flags);
-
- // translate to physical address
- Fault fault = cpuXC->translateDataReadReq(memReq);
-
- // if we have a cache, do cache access too
- if (fault == NoFault && dcacheInterface) {
- memReq->cmd = Read;
- memReq->completionEvent = NULL;
- memReq->time = curTick;
- memReq->flags &= ~INST_READ;
- MemAccessResult result = dcacheInterface->access(memReq);
-
- // Ugly hack to get an event scheduled *only* if the access is
- // a miss. We really should add first-class support for this
- // at some point.
- if (result != MA_HIT && dcacheInterface->doEvents()) {
- memReq->completionEvent = &cacheCompletionEvent;
- lastDcacheStall = curTick;
- unscheduleTickEvent();
- _status = DcacheMissStall;
- } else {
- // do functional access
- fault = cpuXC->read(memReq, data);
-
- }
- } else if(fault == NoFault) {
- // do functional access
- fault = cpuXC->read(memReq, data);
-
- }
-
- if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
- recordEvent("Uncached Read");
-
- return fault;
-}
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-
-template
-Fault
-SimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
-
-template
-Fault
-SimpleCPU::read(Addr addr, uint32_t &data, unsigned flags);
-
-template
-Fault
-SimpleCPU::read(Addr addr, uint16_t &data, unsigned flags);
-
-template
-Fault
-SimpleCPU::read(Addr addr, uint8_t &data, unsigned flags);
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS
-
-template<>
-Fault
-SimpleCPU::read(Addr addr, double &data, unsigned flags)
-{
- return read(addr, *(uint64_t*)&data, flags);
-}
-
-template<>
-Fault
-SimpleCPU::read(Addr addr, float &data, unsigned flags)
-{
- return read(addr, *(uint32_t*)&data, flags);
-}
-
-
-template<>
-Fault
-SimpleCPU::read(Addr addr, int32_t &data, unsigned flags)
-{
- return read(addr, (uint32_t&)data, flags);
-}
-
-
-template <class T>
-Fault
-SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
-{
- memReq->reset(addr, sizeof(T), flags);
-
- // translate to physical address
- Fault fault = cpuXC->translateDataWriteReq(memReq);
-
- // do functional access
- if (fault == NoFault)
- fault = cpuXC->write(memReq, data);
-
- if (fault == NoFault && dcacheInterface) {
- memReq->cmd = Write;
- memcpy(memReq->data,(uint8_t *)&data,memReq->size);
- memReq->completionEvent = NULL;
- memReq->time = curTick;
- memReq->flags &= ~INST_READ;
- MemAccessResult result = dcacheInterface->access(memReq);
-
- // Ugly hack to get an event scheduled *only* if the access is
- // a miss. We really should add first-class support for this
- // at some point.
- if (result != MA_HIT && dcacheInterface->doEvents()) {
- memReq->completionEvent = &cacheCompletionEvent;
- lastDcacheStall = curTick;
- unscheduleTickEvent();
- _status = DcacheMissStall;
- }
- }
-
- if (res && (fault == NoFault))
- *res = memReq->result;
-
- if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
- recordEvent("Uncached Write");
-
- return fault;
-}
-
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-template
-Fault
-SimpleCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
-
-template
-Fault
-SimpleCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
-
-template
-Fault
-SimpleCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
-
-template
-Fault
-SimpleCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS
-
-template<>
-Fault
-SimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
-{
- return write(*(uint64_t*)&data, addr, flags, res);
-}
-
-template<>
-Fault
-SimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
-{
- return write(*(uint32_t*)&data, addr, flags, res);
-}
-
-
-template<>
-Fault
-SimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
-{
- return write((uint32_t)data, addr, flags, res);
-}
-
-
-#if FULL_SYSTEM
-Addr
-SimpleCPU::dbg_vtophys(Addr addr)
-{
- return vtophys(xcProxy, addr);
-}
-#endif // FULL_SYSTEM
-
-void
-SimpleCPU::processCacheCompletion()
-{
- switch (status()) {
- case IcacheMissStall:
- icacheStallCycles += curTick - lastIcacheStall;
- _status = IcacheMissComplete;
- scheduleTickEvent(1);
- break;
- case DcacheMissStall:
- if (memReq->cmd.isRead()) {
- curStaticInst->execute(this,traceData);
- if (traceData)
- traceData->finalize();
- }
- dcacheStallCycles += curTick - lastDcacheStall;
- _status = Running;
- scheduleTickEvent(1);
- break;
- case DcacheMissSwitch:
- if (memReq->cmd.isRead()) {
- curStaticInst->execute(this,traceData);
- if (traceData)
- traceData->finalize();
- }
- _status = SwitchedOut;
- sampler->signalSwitched();
- case SwitchedOut:
- // If this CPU has been switched out due to sampling/warm-up,
- // ignore any further status changes (e.g., due to cache
- // misses outstanding at the time of the switch).
- return;
- default:
- panic("SimpleCPU::processCacheCompletion: bad state");
- break;
- }
-}
-
-#if FULL_SYSTEM
-void
-SimpleCPU::post_interrupt(int int_num, int index)
-{
- BaseCPU::post_interrupt(int_num, index);
-
- if (cpuXC->status() == ExecContext::Suspended) {
- DPRINTF(IPI,"Suspended Processor awoke\n");
- cpuXC->activate();
- }
-}
-#endif // FULL_SYSTEM
-
-/* start simulation, program loaded, processor precise state initialized */
-void
-SimpleCPU::tick()
-{
- numCycles++;
-
- traceData = NULL;
-
- Fault fault = NoFault;
-
-#if FULL_SYSTEM
- if (checkInterrupts && check_interrupts() && !cpuXC->inPalMode() &&
- status() != IcacheMissComplete) {
- int ipl = 0;
- int summary = 0;
- checkInterrupts = false;
-
- if (cpuXC->readMiscReg(IPR_SIRR)) {
- for (int i = INTLEVEL_SOFTWARE_MIN;
- i < INTLEVEL_SOFTWARE_MAX; i++) {
- if (cpuXC->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
- // See table 4-19 of 21164 hardware reference
- ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- uint64_t interrupts = cpuXC->cpu->intr_status();
- for (int i = INTLEVEL_EXTERNAL_MIN;
- i < INTLEVEL_EXTERNAL_MAX; i++) {
- if (interrupts & (ULL(1) << i)) {
- // See table 4-19 of 21164 hardware reference
- ipl = i;
- summary |= (ULL(1) << i);
- }
- }
-
- if (cpuXC->readMiscReg(IPR_ASTRR))
- panic("asynchronous traps not implemented\n");
-
- if (ipl && ipl > cpuXC->readMiscReg(IPR_IPLR)) {
- cpuXC->setMiscReg(IPR_ISR, summary);
- cpuXC->setMiscReg(IPR_INTID, ipl);
-
- Fault(new InterruptFault)->invoke(xcProxy);
-
- DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
- cpuXC->readMiscReg(IPR_IPLR), ipl, summary);
- }
- }
-#endif
-
- // maintain $r0 semantics
- cpuXC->setIntReg(ZeroReg, 0);
-#ifdef TARGET_ALPHA
- cpuXC->setFloatRegDouble(ZeroReg, 0.0);
-#endif // TARGET_ALPHA
-
- if (status() == IcacheMissComplete) {
- // We've already fetched an instruction and were stalled on an
- // I-cache miss. No need to fetch it again.
-
- // Set status to running; tick event will get rescheduled if
- // necessary at end of tick() function.
- _status = Running;
- }
- else {
- // Try to fetch an instruction
-
- // set up memory request for instruction fetch
-#if FULL_SYSTEM
-#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0
-#else
-#define IFETCH_FLAGS(pc) 0
-#endif
-
- memReq->cmd = Read;
- memReq->reset(cpuXC->readPC() & ~3, sizeof(uint32_t),
- IFETCH_FLAGS(cpuXC->readPC()));
-
- fault = cpuXC->translateInstReq(memReq);
-
- if (fault == NoFault)
- fault = cpuXC->mem->read(memReq, inst);
-
- if (icacheInterface && fault == NoFault) {
- memReq->completionEvent = NULL;
-
- memReq->time = curTick;
- memReq->flags |= INST_READ;
- MemAccessResult result = icacheInterface->access(memReq);
-
- // Ugly hack to get an event scheduled *only* if the access is
- // a miss. We really should add first-class support for this
- // at some point.
- if (result != MA_HIT && icacheInterface->doEvents()) {
- memReq->completionEvent = &cacheCompletionEvent;
- lastIcacheStall = curTick;
- unscheduleTickEvent();
- _status = IcacheMissStall;
- return;
- }
- }
- }
-
- // If we've got a valid instruction (i.e., no fault on instruction
- // fetch), then execute it.
- if (fault == NoFault) {
-
- // keep an instruction count
- numInst++;
- numInsts++;
-
- // check for instruction-count-based events
- comInstEventQueue[0]->serviceEvents(numInst);
-
- // decode the instruction
- inst = gtoh(inst);
- curStaticInst = StaticInst::decode(makeExtMI(inst, cpuXC->readPC()));
-
- traceData = Trace::getInstRecord(curTick, xcProxy, this, curStaticInst,
- cpuXC->readPC());
-
-#if FULL_SYSTEM
- cpuXC->setInst(inst);
-#endif // FULL_SYSTEM
-
- cpuXC->func_exe_inst++;
-
- fault = curStaticInst->execute(this, traceData);
-
-#if FULL_SYSTEM
- if (system->kernelBinning->fnbin) {
- assert(cpuXC->getKernelStats());
- system->kernelBinning->execute(xcProxy, inst);
- }
-
- if (cpuXC->profile) {
- bool usermode =
- (cpuXC->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
- cpuXC->profilePC = usermode ? 1 : cpuXC->readPC();
- ProfileNode *node = cpuXC->profile->consume(xcProxy, inst);
- if (node)
- cpuXC->profileNode = node;
- }
-#endif
-
- if (curStaticInst->isMemRef()) {
- numMemRefs++;
- }
-
- if (curStaticInst->isLoad()) {
- ++numLoad;
- comLoadEventQueue[0]->serviceEvents(numLoad);
- }
-
- // If we have a dcache miss, then we can't finialize the instruction
- // trace yet because we want to populate it with the data later
- if (traceData &&
- !(status() == DcacheMissStall && memReq->cmd.isRead())) {
- traceData->finalize();
- }
-
- traceFunctions(cpuXC->readPC());
-
- } // if (fault == NoFault)
-
- if (fault != NoFault) {
-#if FULL_SYSTEM
- fault->invoke(xcProxy);
-#else // !FULL_SYSTEM
- fatal("fault (%d) detected @ PC 0x%08p", fault, cpuXC->readPC());
-#endif // FULL_SYSTEM
- }
- else {
-#if THE_ISA != MIPS_ISA
- // go to the next instruction
- cpuXC->setPC(cpuXC->readNextPC());
- cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst));
-#else
- // go to the next instruction
- cpuXC->setPC(cpuXC->readNextPC());
- cpuXC->setNextPC(cpuXC->readNextNPC());
- cpuXC->setNextNPC(cpuXC->readNextNPC() + sizeof(MachInst));
-#endif
-
- }
-
-#if FULL_SYSTEM
- Addr oldpc;
- do {
- oldpc = cpuXC->readPC();
- system->pcEventQueue.service(xcProxy);
- } while (oldpc != cpuXC->readPC());
-#endif
-
- assert(status() == Running ||
- status() == Idle ||
- status() == DcacheMissStall);
-
- if (status() == Running && !tickEvent.scheduled())
- tickEvent.schedule(curTick + cycles(1));
-}
-
-////////////////////////////////////////////////////////////////////////
-//
-// SimpleCPU Simulation Object
-//
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
-
- Param<Counter> max_insts_any_thread;
- Param<Counter> max_insts_all_threads;
- Param<Counter> max_loads_any_thread;
- Param<Counter> max_loads_all_threads;
-
-#if FULL_SYSTEM
- SimObjectParam<AlphaITB *> itb;
- SimObjectParam<AlphaDTB *> dtb;
- SimObjectParam<FunctionalMemory *> mem;
- SimObjectParam<System *> system;
- Param<int> cpu_id;
- Param<Tick> profile;
-#else
- SimObjectParam<Process *> workload;
-#endif // FULL_SYSTEM
-
- Param<int> clock;
- SimObjectParam<BaseMem *> icache;
- SimObjectParam<BaseMem *> dcache;
-
- Param<bool> defer_registration;
- Param<int> width;
- Param<bool> function_trace;
- Param<Tick> function_trace_start;
-
-END_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
-
- INIT_PARAM(max_insts_any_thread,
- "terminate when any thread reaches this inst count"),
- INIT_PARAM(max_insts_all_threads,
- "terminate when all threads have reached this inst count"),
- INIT_PARAM(max_loads_any_thread,
- "terminate when any thread reaches this load count"),
- INIT_PARAM(max_loads_all_threads,
- "terminate when all threads have reached this load count"),
-
-#if FULL_SYSTEM
- INIT_PARAM(itb, "Instruction TLB"),
- INIT_PARAM(dtb, "Data TLB"),
- INIT_PARAM(mem, "memory"),
- INIT_PARAM(system, "system object"),
- INIT_PARAM(cpu_id, "processor ID"),
- INIT_PARAM(profile, ""),
-#else
- INIT_PARAM(workload, "processes to run"),
-#endif // FULL_SYSTEM
-
- INIT_PARAM(clock, "clock speed"),
- INIT_PARAM(icache, "L1 instruction cache object"),
- INIT_PARAM(dcache, "L1 data cache object"),
- INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
- INIT_PARAM(width, "cpu width"),
- INIT_PARAM(function_trace, "Enable function trace"),
- INIT_PARAM(function_trace_start, "Cycle to start function trace")
-
-END_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
-
-
-CREATE_SIM_OBJECT(SimpleCPU)
-{
- SimpleCPU::Params *params = new SimpleCPU::Params();
- params->name = getInstanceName();
- params->numberOfThreads = 1;
- params->max_insts_any_thread = max_insts_any_thread;
- params->max_insts_all_threads = max_insts_all_threads;
- params->max_loads_any_thread = max_loads_any_thread;
- params->max_loads_all_threads = max_loads_all_threads;
- params->deferRegistration = defer_registration;
- params->clock = clock;
- params->functionTrace = function_trace;
- params->functionTraceStart = function_trace_start;
- params->icache_interface = (icache) ? icache->getInterface() : NULL;
- params->dcache_interface = (dcache) ? dcache->getInterface() : NULL;
- params->width = width;
-
-#if FULL_SYSTEM
- params->itb = itb;
- params->dtb = dtb;
- params->mem = mem;
- params->system = system;
- params->cpu_id = cpu_id;
- params->profile = profile;
-#else
- params->process = workload;
-#endif
-
- SimpleCPU *cpu = new SimpleCPU(params);
- return cpu;
-}
-
-REGISTER_SIM_OBJECT("SimpleCPU", SimpleCPU)
-
diff --git a/cpu/simple/cpu.hh b/cpu/simple/cpu.hh
deleted file mode 100644
index 4ab9a1c3e..000000000
--- a/cpu/simple/cpu.hh
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
-#define __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
-
-#include "base/statistics.hh"
-#include "config/full_system.hh"
-#include "cpu/base.hh"
-#include "cpu/cpu_exec_context.hh"
-#include "cpu/pc_event.hh"
-#include "cpu/sampler/sampler.hh"
-#include "cpu/static_inst.hh"
-#include "sim/eventq.hh"
-
-// forward declarations
-#if FULL_SYSTEM
-class Processor;
-class AlphaITB;
-class AlphaDTB;
-class PhysicalMemory;
-
-class RemoteGDB;
-class GDBListener;
-
-#else
-
-class Process;
-
-#endif // FULL_SYSTEM
-
-class ExecContext;
-class MemInterface;
-class Checkpoint;
-
-namespace Trace {
- class InstRecord;
-}
-
-class SimpleCPU : public BaseCPU
-{
- protected:
- typedef TheISA::MachInst MachInst;
- typedef TheISA::MiscReg MiscReg;
- public:
- // main simulation loop (one cycle)
- void tick();
- virtual void init();
-
- private:
- struct TickEvent : public Event
- {
- SimpleCPU *cpu;
- int width;
-
- TickEvent(SimpleCPU *c, int w);
- void process();
- const char *description();
- };
-
- TickEvent tickEvent;
-
- /// Schedule tick event, regardless of its current state.
- void scheduleTickEvent(int numCycles)
- {
- if (tickEvent.squashed())
- tickEvent.reschedule(curTick + cycles(numCycles));
- else if (!tickEvent.scheduled())
- tickEvent.schedule(curTick + cycles(numCycles));
- }
-
- /// Unschedule tick event, regardless of its current state.
- void unscheduleTickEvent()
- {
- if (tickEvent.scheduled())
- tickEvent.squash();
- }
-
- private:
- Trace::InstRecord *traceData;
-
- public:
- //
- enum Status {
- Running,
- Idle,
- IcacheMissStall,
- IcacheMissComplete,
- DcacheMissStall,
- DcacheMissSwitch,
- SwitchedOut
- };
-
- private:
- Status _status;
-
- public:
- void post_interrupt(int int_num, int index);
-
- void zero_fill_64(Addr addr) {
- static int warned = 0;
- if (!warned) {
- warn ("WH64 is not implemented");
- warned = 1;
- }
- };
-
- public:
- struct Params : public BaseCPU::Params
- {
- MemInterface *icache_interface;
- MemInterface *dcache_interface;
- int width;
-#if FULL_SYSTEM
- AlphaITB *itb;
- AlphaDTB *dtb;
- FunctionalMemory *mem;
-#else
- Process *process;
-#endif
- };
- SimpleCPU(Params *params);
- virtual ~SimpleCPU();
-
- public:
- // execution context
- CPUExecContext *cpuXC;
-
- ExecContext *xcProxy;
-
- void switchOut(Sampler *s);
- void takeOverFrom(BaseCPU *oldCPU);
-
-#if FULL_SYSTEM
- Addr dbg_vtophys(Addr addr);
-
- bool interval_stats;
-#endif
-
- // L1 instruction cache
- MemInterface *icacheInterface;
-
- // L1 data cache
- MemInterface *dcacheInterface;
-
- // current instruction
- MachInst inst;
-
- // Refcounted pointer to the one memory request.
- MemReqPtr memReq;
-
- // Pointer to the sampler that is telling us to switchover.
- // Used to signal the completion of the pipe drain and schedule
- // the next switchover
- Sampler *sampler;
-
- StaticInstPtr curStaticInst;
-
- class CacheCompletionEvent : public Event
- {
- private:
- SimpleCPU *cpu;
-
- public:
- CacheCompletionEvent(SimpleCPU *_cpu);
-
- virtual void process();
- virtual const char *description();
- };
-
- CacheCompletionEvent cacheCompletionEvent;
-
- Status status() const { return _status; }
-
- virtual void activateContext(int thread_num, int delay);
- virtual void suspendContext(int thread_num);
- virtual void deallocateContext(int thread_num);
- virtual void haltContext(int thread_num);
-
- // statistics
- virtual void regStats();
- virtual void resetStats();
-
- // number of simulated instructions
- Counter numInst;
- Counter startNumInst;
- Stats::Scalar<> numInsts;
-
- virtual Counter totalInstructions() const
- {
- return numInst - startNumInst;
- }
-
- // number of simulated memory references
- Stats::Scalar<> numMemRefs;
-
- // number of simulated loads
- Counter numLoad;
- Counter startNumLoad;
-
- // number of idle cycles
- Stats::Average<> notIdleFraction;
- Stats::Formula idleFraction;
-
- // number of cycles stalled for I-cache misses
- Stats::Scalar<> icacheStallCycles;
- Counter lastIcacheStall;
-
- // number of cycles stalled for D-cache misses
- Stats::Scalar<> dcacheStallCycles;
- Counter lastDcacheStall;
-
- void processCacheCompletion();
-
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-
- template <class T>
- Fault read(Addr addr, T &data, unsigned flags);
-
- template <class T>
- Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
-
- // These functions are only used in CPU models that split
- // effective address computation from the actual memory access.
- void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
- Addr getEA() { panic("SimpleCPU::getEA() not implemented\n"); }
-
- void prefetch(Addr addr, unsigned flags)
- {
- // need to do this...
- }
-
- void writeHint(Addr addr, int size, unsigned flags)
- {
- // need to do this...
- }
-
- Fault copySrcTranslate(Addr src);
-
- Fault copy(Addr dest);
-
- // The register accessor methods provide the index of the
- // instruction's operand (e.g., 0 or 1), not the architectural
- // register index, to simplify the implementation of register
- // renaming. We find the architectural register index by indexing
- // into the instruction's own operand index table. Note that a
- // raw pointer to the StaticInst is provided instead of a
- // ref-counted StaticInstPtr to redice overhead. This is fine as
- // long as these methods don't copy the pointer into any long-term
- // storage (which is pretty hard to imagine they would have reason
- // to do).
-
- uint64_t readIntReg(const StaticInst *si, int idx)
- {
- return cpuXC->readIntReg(si->srcRegIdx(idx));
- }
-
- float readFloatRegSingle(const StaticInst *si, int idx)
- {
- int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return cpuXC->readFloatRegSingle(reg_idx);
- }
-
- double readFloatRegDouble(const StaticInst *si, int idx)
- {
- int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return cpuXC->readFloatRegDouble(reg_idx);
- }
-
- uint64_t readFloatRegInt(const StaticInst *si, int idx)
- {
- int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return cpuXC->readFloatRegInt(reg_idx);
- }
-
- void setIntReg(const StaticInst *si, int idx, uint64_t val)
- {
- cpuXC->setIntReg(si->destRegIdx(idx), val);
- }
-
- void setFloatRegSingle(const StaticInst *si, int idx, float val)
- {
- int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- cpuXC->setFloatRegSingle(reg_idx, val);
- }
-
- void setFloatRegDouble(const StaticInst *si, int idx, double val)
- {
- int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- cpuXC->setFloatRegDouble(reg_idx, val);
- }
-
- void setFloatRegInt(const StaticInst *si, int idx, uint64_t val)
- {
- int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- cpuXC->setFloatRegInt(reg_idx, val);
- }
-
- uint64_t readPC() { return cpuXC->readPC(); }
- void setNextPC(uint64_t val) { cpuXC->setNextPC(val); }
-
- MiscReg readMiscReg(int misc_reg)
- {
- return cpuXC->readMiscReg(misc_reg);
- }
-
- MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
- {
- return cpuXC->readMiscRegWithEffect(misc_reg, fault);
- }
-
- Fault setMiscReg(int misc_reg, const MiscReg &val)
- {
- return cpuXC->setMiscReg(misc_reg, val);
- }
-
- Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
- {
- return cpuXC->setMiscRegWithEffect(misc_reg, val);
- }
-
-#if FULL_SYSTEM
- Fault hwrei() { return cpuXC->hwrei(); }
- int readIntrFlag() { return cpuXC->readIntrFlag(); }
- void setIntrFlag(int val) { cpuXC->setIntrFlag(val); }
- bool inPalMode() { return cpuXC->inPalMode(); }
- void ev5_trap(Fault fault) { fault->invoke(xcProxy); }
- bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); }
-#else
- void syscall() { cpuXC->syscall(); }
-#endif
-
- bool misspeculating() { return cpuXC->misspeculating(); }
- ExecContext *xcBase() { return xcProxy; }
-};
-
-#endif // __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
diff --git a/cpu/smt.hh b/cpu/smt.hh
deleted file mode 100644
index 9c52abf95..000000000
--- a/cpu/smt.hh
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * Defines SMT_MAX_THREADS.
- */
-
-#ifndef __SMT_HH__
-#define __SMT_HH__
-
-#ifndef SMT_MAX_THREADS
-/** The number of TPUs in any processor. */
-#define SMT_MAX_THREADS 4
-#endif
-
-/**
- * The maximum number of active threads across all cpus. Used to
- * initialize per-thread statistics in the cache.
- *
- * NB: Be careful to only use it once all the CPUs that you care about
- * have been initialized
- */
-extern int maxThreadsPerCPU;
-
-/**
- * Changes the status and priority of the thread with the given number.
- * @param thread_number The thread to change.
- * @param activate The new active status.
- * @param priority The new priority.
- */
-void change_thread_state(int thread_number, int activate, int priority);
-
-#endif // __SMT_HH__
diff --git a/cpu/static_inst.cc b/cpu/static_inst.cc
deleted file mode 100644
index c307dc6fc..000000000
--- a/cpu/static_inst.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <iostream>
-#include "cpu/static_inst.hh"
-#include "sim/root.hh"
-
-StaticInstPtr StaticInst::nullStaticInstPtr;
-
-// Define the decode cache hash map.
-StaticInst::DecodeCache StaticInst::decodeCache;
-
-void
-StaticInst::dumpDecodeCacheStats()
-{
- using namespace std;
-
- cerr << "Decode hash table stats @ " << curTick << ":" << endl;
- cerr << "\tnum entries = " << decodeCache.size() << endl;
- cerr << "\tnum buckets = " << decodeCache.bucket_count() << endl;
- vector<int> hist(100, 0);
- int max_hist = 0;
- for (int i = 0; i < decodeCache.bucket_count(); ++i) {
- int count = decodeCache.elems_in_bucket(i);
- if (count > max_hist)
- max_hist = count;
- hist[count]++;
- }
- for (int i = 0; i <= max_hist; ++i) {
- cerr << "\tbuckets of size " << i << " = " << hist[i] << endl;
- }
-}
-
-bool
-StaticInst::hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt) const
-{
- if (isDirectCtrl()) {
- tgt = branchTarget(pc);
- return true;
- }
-
- if (isIndirectCtrl()) {
- tgt = branchTarget(xc);
- return true;
- }
-
- return false;
-}
-
diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh
deleted file mode 100644
index b9d782b7b..000000000
--- a/cpu/static_inst.hh
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_STATIC_INST_HH__
-#define __CPU_STATIC_INST_HH__
-
-#include <bitset>
-#include <string>
-
-#include "base/hashmap.hh"
-#include "base/refcnt.hh"
-#include "encumbered/cpu/full/op_class.hh"
-#include "sim/host.hh"
-#include "arch/isa_traits.hh"
-
-// forward declarations
-struct AlphaSimpleImpl;
-struct OzoneImpl;
-struct SimpleImpl;
-class ExecContext;
-class DynInst;
-
-template <class Impl>
-class AlphaDynInst;
-
-template <class Impl>
-class OzoneDynInst;
-
-class CheckerCPU;
-class FastCPU;
-class SimpleCPU;
-class InorderCPU;
-class SymbolTable;
-
-namespace Trace {
- class InstRecord;
-}
-
-/**
- * Base, ISA-independent static instruction class.
- *
- * The main component of this class is the vector of flags and the
- * associated methods for reading them. Any object that can rely
- * solely on these flags can process instructions without being
- * recompiled for multiple ISAs.
- */
-class StaticInstBase : public RefCounted
-{
- protected:
-
- /// Set of boolean static instruction properties.
- ///
- /// Notes:
- /// - The IsInteger and IsFloating flags are based on the class of
- /// registers accessed by the instruction. Although most
- /// instructions will have exactly one of these two flags set, it
- /// is possible for an instruction to have neither (e.g., direct
- /// unconditional branches, memory barriers) or both (e.g., an
- /// FP/int conversion).
- /// - If IsMemRef is set, then exactly one of IsLoad or IsStore
- /// will be set.
- /// - If IsControl is set, then exactly one of IsDirectControl or
- /// IsIndirect Control will be set, and exactly one of
- /// IsCondControl or IsUncondControl will be set.
- /// - IsSerializing, IsMemBarrier, and IsWriteBarrier are
- /// implemented as flags since in the current model there's no
- /// other way for instructions to inject behavior into the
- /// pipeline outside of fetch. Once we go to an exec-in-exec CPU
- /// model we should be able to get rid of these flags and
- /// implement this behavior via the execute() methods.
- ///
- enum Flags {
- IsNop, ///< Is a no-op (no effect at all).
-
- IsInteger, ///< References integer regs.
- IsFloating, ///< References FP regs.
-
- IsMemRef, ///< References memory (load, store, or prefetch).
- IsLoad, ///< Reads from memory (load or prefetch).
- IsStore, ///< Writes to memory.
- IsStoreConditional, ///< Store conditional instruction.
- IsInstPrefetch, ///< Instruction-cache prefetch.
- IsDataPrefetch, ///< Data-cache prefetch.
- IsCopy, ///< Fast Cache block copy
-
- IsControl, ///< Control transfer instruction.
- IsDirectControl, ///< PC relative control transfer.
- IsIndirectControl, ///< Register indirect control transfer.
- IsCondControl, ///< Conditional control transfer.
- IsUncondControl, ///< Unconditional control transfer.
- IsCall, ///< Subroutine call.
- IsReturn, ///< Subroutine return.
-
- IsCondDelaySlot,///< Conditional Delay-Slot Instruction
-
- IsThreadSync, ///< Thread synchronization operation.
-
- IsSerializing, ///< Serializes pipeline: won't execute until all
- /// older instructions have committed.
- IsSerializeBefore,
- IsSerializeAfter,
- IsMemBarrier, ///< Is a memory barrier
- IsWriteBarrier, ///< Is a write barrier
-
- IsNonSpeculative, ///< Should not be executed speculatively
- IsQuiesce, ///< Is a quiesce instruction
-
- IsIprAccess, ///< Accesses IPRs
- IsUnverifiable, ///< Can't be verified by a checker
-
- NumFlags
- };
-
- /// Flag values for this instruction.
- std::bitset<NumFlags> flags;
-
- /// See opClass().
- OpClass _opClass;
-
- /// See numSrcRegs().
- int8_t _numSrcRegs;
-
- /// See numDestRegs().
- int8_t _numDestRegs;
-
- /// The following are used to track physical register usage
- /// for machines with separate int & FP reg files.
- //@{
- int8_t _numFPDestRegs;
- int8_t _numIntDestRegs;
- //@}
-
- /// Constructor.
- /// It's important to initialize everything here to a sane
- /// default, since the decoder generally only overrides
- /// the fields that are meaningful for the particular
- /// instruction.
- StaticInstBase(OpClass __opClass)
- : _opClass(__opClass), _numSrcRegs(0), _numDestRegs(0),
- _numFPDestRegs(0), _numIntDestRegs(0)
- {
- }
-
- public:
-
- /// @name Register information.
- /// The sum of numFPDestRegs() and numIntDestRegs() equals
- /// numDestRegs(). The former two functions are used to track
- /// physical register usage for machines with separate int & FP
- /// reg files.
- //@{
- /// Number of source registers.
- int8_t numSrcRegs() const { return _numSrcRegs; }
- /// Number of destination registers.
- int8_t numDestRegs() const { return _numDestRegs; }
- /// Number of floating-point destination regs.
- int8_t numFPDestRegs() const { return _numFPDestRegs; }
- /// Number of integer destination regs.
- int8_t numIntDestRegs() const { return _numIntDestRegs; }
- //@}
-
- /// @name Flag accessors.
- /// These functions are used to access the values of the various
- /// instruction property flags. See StaticInstBase::Flags for descriptions
- /// of the individual flags.
- //@{
-
- bool isNop() const { return flags[IsNop]; }
-
- bool isMemRef() const { return flags[IsMemRef]; }
- bool isLoad() const { return flags[IsLoad]; }
- bool isStore() const { return flags[IsStore]; }
- bool isStoreConditional() const { return flags[IsStoreConditional]; }
- bool isInstPrefetch() const { return flags[IsInstPrefetch]; }
- bool isDataPrefetch() const { return flags[IsDataPrefetch]; }
- bool isCopy() const { return flags[IsCopy];}
-
- bool isInteger() const { return flags[IsInteger]; }
- bool isFloating() const { return flags[IsFloating]; }
-
- bool isControl() const { return flags[IsControl]; }
- bool isCall() const { return flags[IsCall]; }
- bool isReturn() const { return flags[IsReturn]; }
- bool isDirectCtrl() const { return flags[IsDirectControl]; }
- bool isIndirectCtrl() const { return flags[IsIndirectControl]; }
- bool isCondCtrl() const { return flags[IsCondControl]; }
- bool isUncondCtrl() const { return flags[IsUncondControl]; }
-
- bool isThreadSync() const { return flags[IsThreadSync]; }
- bool isSerializing() const { return flags[IsSerializing] ||
- flags[IsSerializeBefore] ||
- flags[IsSerializeAfter]; }
- bool isSerializeBefore() const { return flags[IsSerializeBefore]; }
- bool isSerializeAfter() const { return flags[IsSerializeAfter]; }
- bool isMemBarrier() const { return flags[IsMemBarrier]; }
- bool isWriteBarrier() const { return flags[IsWriteBarrier]; }
- bool isNonSpeculative() const { return flags[IsNonSpeculative]; }
- bool isQuiesce() const { return flags[IsQuiesce]; }
- bool isIprAccess() const { return flags[IsIprAccess]; }
- bool isUnverifiable() const { return flags[IsUnverifiable]; }
- //@}
-
- /// Operation class. Used to select appropriate function unit in issue.
- OpClass opClass() const { return _opClass; }
-};
-
-
-// forward declaration
-class StaticInstPtr;
-
-/**
- * Generic yet ISA-dependent static instruction class.
- *
- * This class builds on StaticInstBase, defining fields and interfaces
- * that are generic across all ISAs but that differ in details
- * according to the specific ISA being used.
- */
-class StaticInst : public StaticInstBase
-{
- public:
-
- /// Binary machine instruction type.
- typedef TheISA::MachInst MachInst;
- /// Binary extended machine instruction type.
- typedef TheISA::ExtMachInst ExtMachInst;
- /// Logical register index type.
- typedef TheISA::RegIndex RegIndex;
-
- enum {
- MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs
- MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs
- };
-
-
- /// Return logical index (architectural reg num) of i'th destination reg.
- /// Only the entries from 0 through numDestRegs()-1 are valid.
- RegIndex destRegIdx(int i) const { return _destRegIdx[i]; }
-
- /// Return logical index (architectural reg num) of i'th source reg.
- /// Only the entries from 0 through numSrcRegs()-1 are valid.
- RegIndex srcRegIdx(int i) const { return _srcRegIdx[i]; }
-
- /// Pointer to a statically allocated "null" instruction object.
- /// Used to give eaCompInst() and memAccInst() something to return
- /// when called on non-memory instructions.
- static StaticInstPtr nullStaticInstPtr;
-
- /**
- * Memory references only: returns "fake" instruction representing
- * the effective address part of the memory operation. Used to
- * obtain the dependence info (numSrcRegs and srcRegIdx[]) for
- * just the EA computation.
- */
- virtual const
- StaticInstPtr &eaCompInst() const { return nullStaticInstPtr; }
-
- /**
- * Memory references only: returns "fake" instruction representing
- * the memory access part of the memory operation. Used to
- * obtain the dependence info (numSrcRegs and srcRegIdx[]) for
- * just the memory access (not the EA computation).
- */
- virtual const
- StaticInstPtr &memAccInst() const { return nullStaticInstPtr; }
-
- /// The binary machine instruction.
- const ExtMachInst machInst;
-
- protected:
-
- /// See destRegIdx().
- RegIndex _destRegIdx[MaxInstDestRegs];
- /// See srcRegIdx().
- RegIndex _srcRegIdx[MaxInstSrcRegs];
-
- /**
- * Base mnemonic (e.g., "add"). Used by generateDisassembly()
- * methods. Also useful to readily identify instructions from
- * within the debugger when #cachedDisassembly has not been
- * initialized.
- */
- const char *mnemonic;
-
- /**
- * String representation of disassembly (lazily evaluated via
- * disassemble()).
- */
- mutable std::string *cachedDisassembly;
-
- /**
- * Internal function to generate disassembly string.
- */
- virtual std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const = 0;
-
- /// Constructor.
- StaticInst(const char *_mnemonic, ExtMachInst _machInst, OpClass __opClass)
- : StaticInstBase(__opClass),
- machInst(_machInst), mnemonic(_mnemonic), cachedDisassembly(0)
- {
- }
-
- public:
-
- virtual ~StaticInst()
- {
- if (cachedDisassembly)
- delete cachedDisassembly;
- }
-
-/**
- * The execute() signatures are auto-generated by scons based on the
- * set of CPU models we are compiling in today.
- */
-#include "cpu/static_inst_exec_sigs.hh"
-
- /**
- * Return the target address for a PC-relative branch.
- * Invalid if not a PC-relative branch (i.e. isDirectCtrl()
- * should be true).
- */
- virtual Addr branchTarget(Addr branchPC) const
- {
- panic("StaticInst::branchTarget() called on instruction "
- "that is not a PC-relative branch.");
- }
-
- /**
- * Return the target address for an indirect branch (jump). The
- * register value is read from the supplied execution context, so
- * the result is valid only if the execution context is about to
- * execute the branch in question. Invalid if not an indirect
- * branch (i.e. isIndirectCtrl() should be true).
- */
- virtual Addr branchTarget(ExecContext *xc) const
- {
- panic("StaticInst::branchTarget() called on instruction "
- "that is not an indirect branch.");
- }
-
- /**
- * Return true if the instruction is a control transfer, and if so,
- * return the target address as well.
- */
- bool hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt) const;
-
- /**
- * Return string representation of disassembled instruction.
- * The default version of this function will call the internal
- * virtual generateDisassembly() function to get the string,
- * then cache it in #cachedDisassembly. If the disassembly
- * should not be cached, this function should be overridden directly.
- */
- virtual const std::string &disassemble(Addr pc,
- const SymbolTable *symtab = 0) const
- {
- if (!cachedDisassembly)
- cachedDisassembly =
- new std::string(generateDisassembly(pc, symtab));
-
- return *cachedDisassembly;
- }
-
- /// Decoded instruction cache type.
- /// For now we're using a generic hash_map; this seems to work
- /// pretty well.
- typedef m5::hash_map<ExtMachInst, StaticInstPtr> DecodeCache;
-
- /// A cache of decoded instruction objects.
- static DecodeCache decodeCache;
-
- /**
- * Dump some basic stats on the decode cache hash map.
- * Only gets called if DECODE_CACHE_HASH_STATS is defined.
- */
- static void dumpDecodeCacheStats();
-
- /// Decode a machine instruction.
- /// @param mach_inst The binary instruction to decode.
- /// @retval A pointer to the corresponding StaticInst object.
- //This is defined as inline below.
- static StaticInstPtr decode(ExtMachInst mach_inst);
-};
-
-typedef RefCountingPtr<StaticInstBase> StaticInstBasePtr;
-
-/// Reference-counted pointer to a StaticInst object.
-/// This type should be used instead of "StaticInst *" so that
-/// StaticInst objects can be properly reference-counted.
-class StaticInstPtr : public RefCountingPtr<StaticInst>
-{
- public:
- /// Constructor.
- StaticInstPtr()
- : RefCountingPtr<StaticInst>()
- {
- }
-
- /// Conversion from "StaticInst *".
- StaticInstPtr(StaticInst *p)
- : RefCountingPtr<StaticInst>(p)
- {
- }
-
- /// Copy constructor.
- StaticInstPtr(const StaticInstPtr &r)
- : RefCountingPtr<StaticInst>(r)
- {
- }
-
- /// Construct directly from machine instruction.
- /// Calls StaticInst::decode().
- StaticInstPtr(TheISA::ExtMachInst mach_inst)
- : RefCountingPtr<StaticInst>(StaticInst::decode(mach_inst))
- {
- }
-
- /// Convert to pointer to StaticInstBase class.
- operator const StaticInstBasePtr()
- {
- return this->get();
- }
-};
-
-inline StaticInstPtr
-StaticInst::decode(StaticInst::ExtMachInst mach_inst)
-{
-#ifdef DECODE_CACHE_HASH_STATS
- // Simple stats on decode hash_map. Turns out the default
- // hash function is as good as anything I could come up with.
- const int dump_every_n = 10000000;
- static int decodes_til_dump = dump_every_n;
-
- if (--decodes_til_dump == 0) {
- dumpDecodeCacheStats();
- decodes_til_dump = dump_every_n;
- }
-#endif
-
- DecodeCache::iterator iter = decodeCache.find(mach_inst);
- if (iter != decodeCache.end()) {
- return iter->second;
- }
-
- StaticInstPtr si = TheISA::decodeInst(mach_inst);
- decodeCache[mach_inst] = si;
- return si;
-}
-
-#endif // __CPU_STATIC_INST_HH__
diff --git a/cpu/thread_state.hh b/cpu/thread_state.hh
deleted file mode 100644
index e09cb12fd..000000000
--- a/cpu/thread_state.hh
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_THREAD_STATE_HH__
-#define __CPU_THREAD_STATE_HH__
-
-#include "cpu/exec_context.hh"
-
-#if FULL_SYSTEM
-class EndQuiesceEvent;
-class FunctionProfile;
-class ProfileNode;
-namespace Kernel {
- class Statistics;
-};
-#else
-class FunctionalMemory;
-class Process;
-#endif
-
-/**
- * Struct for holding general thread state that is needed across CPU
- * models. This includes things such as pointers to the process,
- * memory, quiesce events, and certain stats. This can be expanded
- * to hold more thread-specific stats within it.
- */
-struct ThreadState {
-#if FULL_SYSTEM
- ThreadState(int _cpuId, int _tid, FunctionalMemory *_mem)
- : cpuId(_cpuId), tid(_tid), mem(_mem), lastActivate(0), lastSuspend(0),
- profile(NULL), profileNode(NULL), profilePC(0), quiesceEvent(NULL)
-#else
- ThreadState(int _cpuId, int _tid, FunctionalMemory *_mem,
- Process *_process, short _asid)
- : cpuId(_cpuId), tid(_tid), mem(_mem), process(_process), asid(_asid)
-#endif
- {
- funcExeInst = 0;
- storeCondFailures = 0;
- }
-
- ExecContext::Status status;
-
- int cpuId;
-
- // Index of hardware thread context on the CPU that this represents.
- int tid;
-
- Counter numInst;
- Stats::Scalar<> numInsts;
- Stats::Scalar<> numMemRefs;
-
- // number of simulated loads
- Counter numLoad;
- Counter startNumLoad;
-
- FunctionalMemory *mem; // functional storage for process address space
-
-#if FULL_SYSTEM
- Tick lastActivate;
- Tick lastSuspend;
-
- FunctionProfile *profile;
- ProfileNode *profileNode;
- Addr profilePC;
-
- EndQuiesceEvent *quiesceEvent;
-
- Kernel::Statistics *kernelStats;
-#else
- Process *process;
-
- // Address space ID. Note that this is used for TIMING cache
- // simulation only; all functional memory accesses should use
- // one of the FunctionalMemory pointers above.
- short asid;
-
-#endif
-
- /**
- * Temporary storage to pass the source address from copy_load to
- * copy_store.
- * @todo Remove this temporary when we have a better way to do it.
- */
- Addr copySrcAddr;
- /**
- * Temp storage for the physical source address of a copy.
- * @todo Remove this temporary when we have a better way to do it.
- */
- Addr copySrcPhysAddr;
-
- /*
- * number of executed instructions, for matching with syscall trace
- * points in EIO files.
- */
- Counter funcExeInst;
-
- //
- // Count failed store conditionals so we can warn of apparent
- // application deadlock situations.
- unsigned storeCondFailures;
-};
-
-#endif // __CPU_THREAD_STATE_HH__
diff --git a/cpu/trace/opt_cpu.cc b/cpu/trace/opt_cpu.cc
deleted file mode 100644
index 6cd23b0dd..000000000
--- a/cpu/trace/opt_cpu.cc
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * Definition of a memory trace CPU object for optimal caches. Uses a memory
- * trace to access a fully associative cache with optimal replacement.
- */
-
-#include <algorithm> // For heap functions.
-
-#include "cpu/trace/opt_cpu.hh"
-#include "cpu/trace/reader/mem_trace_reader.hh"
-
-#include "sim/builder.hh"
-#include "sim/sim_events.hh"
-
-using namespace std;
-
-OptCPU::OptCPU(const string &name,
- MemTraceReader *_trace,
- int block_size,
- int cache_size,
- int _assoc)
- : SimObject(name), tickEvent(this), trace(_trace),
- numBlks(cache_size/block_size), assoc(_assoc), numSets(numBlks/assoc),
- setMask(numSets - 1)
-{
- int log_block_size = 0;
- int tmp_block_size = block_size;
- while (tmp_block_size > 1) {
- ++log_block_size;
- tmp_block_size = tmp_block_size >> 1;
- }
- assert(1<<log_block_size == block_size);
- MemReqPtr req;
- trace->getNextReq(req);
- refInfo.resize(numSets);
- while (req) {
- RefInfo temp;
- temp.addr = req->paddr >> log_block_size;
- int set = temp.addr & setMask;
- refInfo[set].push_back(temp);
- trace->getNextReq(req);
- }
-
- // Initialize top level of lookup table.
- lookupTable.resize(16);
-
- // Annotate references with next ref time.
- for (int k = 0; k < numSets; ++k) {
- for (RefIndex i = refInfo[k].size() - 1; i >= 0; --i) {
- Addr addr = refInfo[k][i].addr;
- initTable(addr, InfiniteRef);
- refInfo[k][i].nextRefTime = lookupValue(addr);
- setValue(addr, i);
- }
- }
-
- // Reset the lookup table
- for (int j = 0; j < 16; ++j) {
- if (lookupTable[j].size() == (1<<16)) {
- for (int k = 0; k < (1<<16); ++k) {
- if (lookupTable[j][k].size() == (1<<16)) {
- for (int l = 0; l < (1<<16); ++l) {
- lookupTable[j][k][l] = -1;
- }
- }
- }
- }
- }
-
- tickEvent.schedule(0);
-
- hits = 0;
- misses = 0;
-}
-
-void
-OptCPU::processSet(int set)
-{
- // Initialize cache
- int blks_in_cache = 0;
- RefIndex i = 0;
- cacheHeap.clear();
- cacheHeap.resize(assoc);
-
- while (blks_in_cache < assoc) {
- RefIndex cache_index = lookupValue(refInfo[set][i].addr);
- if (cache_index == -1) {
- // First reference to this block
- misses++;
- cache_index = blks_in_cache++;
- setValue(refInfo[set][i].addr, cache_index);
- } else {
- hits++;
- }
- // update cache heap to most recent reference
- cacheHeap[cache_index] = i;
- if (++i >= refInfo[set].size()) {
- return;
- }
- }
- for (int start = assoc/2; start >= 0; --start) {
- heapify(set,start);
- }
- //verifyHeap(set,0);
-
- for (; i < refInfo[set].size(); ++i) {
- RefIndex cache_index = lookupValue(refInfo[set][i].addr);
- if (cache_index == -1) {
- // miss
- misses++;
- // replace from cacheHeap[0]
- // mark replaced block as absent
- setValue(refInfo[set][cacheHeap[0]].addr, -1);
- setValue(refInfo[set][i].addr, 0);
- cacheHeap[0] = i;
- heapify(set, 0);
- // Make sure its in the cache
- assert(lookupValue(refInfo[set][i].addr) != -1);
- } else {
- // hit
- hits++;
- assert(refInfo[set][cacheHeap[cache_index]].addr ==
- refInfo[set][i].addr);
- assert(refInfo[set][cacheHeap[cache_index]].nextRefTime == i);
- assert(heapLeft(cache_index) >= assoc);
-
- cacheHeap[cache_index] = i;
- processRankIncrease(set, cache_index);
- assert(lookupValue(refInfo[set][i].addr) != -1);
- }
- }
-}
-void
-OptCPU::tick()
-{
- // Do opt simulation
-
- int references = 0;
- for (int set = 0; set < numSets; ++set) {
- if (!refInfo[set].empty()) {
- processSet(set);
- }
- references += refInfo[set].size();
- }
- // exit;
- fprintf(stderr,"sys.cpu.misses %d #opt cache misses\n",misses);
- fprintf(stderr,"sys.cpu.hits %d #opt cache hits\n", hits);
- fprintf(stderr,"sys.cpu.accesses %d #opt cache acceses\n", references);
- new SimExitEvent("Finshed Memory Trace");
-}
-
-void
-OptCPU::initTable(Addr addr, RefIndex index)
-{
- int l1_index = (addr >> 32) & 0x0f;
- int l2_index = (addr >> 16) & 0xffff;
- assert(l1_index == addr >> 32);
- if (lookupTable[l1_index].size() != (1<<16)) {
- lookupTable[l1_index].resize(1<<16);
- }
- if (lookupTable[l1_index][l2_index].size() != (1<<16)) {
- lookupTable[l1_index][l2_index].resize(1<<16, index);
- }
-}
-
-OptCPU::TickEvent::TickEvent(OptCPU *c)
- : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
-{
-}
-
-void
-OptCPU::TickEvent::process()
-{
- cpu->tick();
-}
-
-const char *
-OptCPU::TickEvent::description()
-{
- return "OptCPU tick event";
-}
-
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(OptCPU)
-
- SimObjectParam<MemTraceReader *> data_trace;
- Param<int> size;
- Param<int> block_size;
-Param<int> assoc;
-
-END_DECLARE_SIM_OBJECT_PARAMS(OptCPU)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(OptCPU)
-
- INIT_PARAM_DFLT(data_trace, "memory trace", NULL),
- INIT_PARAM(size, "cache size"),
- INIT_PARAM(block_size, "block size"),
- INIT_PARAM(assoc,"associativity")
-
-END_INIT_SIM_OBJECT_PARAMS(OptCPU)
-
-CREATE_SIM_OBJECT(OptCPU)
-{
- return new OptCPU(getInstanceName(),
- data_trace,
- block_size,
- size,
- assoc);
-}
-
-REGISTER_SIM_OBJECT("OptCPU", OptCPU)
diff --git a/cpu/trace/opt_cpu.hh b/cpu/trace/opt_cpu.hh
deleted file mode 100644
index f81691733..000000000
--- a/cpu/trace/opt_cpu.hh
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * Declaration of a memory trace CPU object for optimal caches. Uses a memory
- * trace to access a fully associative cache with optimal replacement.
- */
-
-#ifndef __CPU_TRACE_OPT_CPU_HH__
-#define __CPU_TRACE_OPT_CPU_HH__
-
-#include <vector>
-
-#include "mem/mem_req.hh" // for MemReqPtr
-#include "sim/eventq.hh" // for Event
-#include "sim/sim_object.hh"
-
-// Forward Declaration
-class MemTraceReader;
-
-/**
- * A CPU object to simulate a fully-associative cache with optimal replacement.
- */
-class OptCPU : public SimObject
-{
- private:
- typedef int RefIndex;
-
- typedef std::vector<RefIndex> L3Table;
- typedef std::vector<L3Table> L2Table;
- typedef std::vector<L2Table> L1Table;
-
- /**
- * Event to call OptCPU::tick
- */
- class TickEvent : public Event
- {
- private:
- /** The associated CPU */
- OptCPU *cpu;
-
- public:
- /**
- * Construct this event;
- */
- TickEvent(OptCPU *c);
-
- /**
- * Call the tick function.
- */
- void process();
-
- /**
- * Return a string description of this event.
- */
- const char *description();
- };
-
- TickEvent tickEvent;
-
- class RefInfo
- {
- public:
- RefIndex nextRefTime;
- Addr addr;
- };
-
- /** Reference Information, per set. */
- std::vector<std::vector<RefInfo> > refInfo;
-
- /** Lookup table to track blocks in the cache heap */
- L1Table lookupTable;
-
- /**
- * Return the correct value in the lookup table.
- */
- RefIndex lookupValue(Addr addr)
- {
- int l1_index = (addr >> 32) & 0x0f;
- int l2_index = (addr >> 16) & 0xffff;
- int l3_index = addr & 0xffff;
- assert(l1_index == addr >> 32);
- return lookupTable[l1_index][l2_index][l3_index];
- }
-
- /**
- * Set the value in the lookup table.
- */
- void setValue(Addr addr, RefIndex index)
- {
- int l1_index = (addr >> 32) & 0x0f;
- int l2_index = (addr >> 16) & 0xffff;
- int l3_index = addr & 0xffff;
- assert(l1_index == addr >> 32);
- lookupTable[l1_index][l2_index][l3_index]=index;
- }
-
- /**
- * Initialize the lookup table to the given value.
- */
- void initTable(Addr addr, RefIndex index);
-
- void heapSwap(int set, int a, int b) {
- RefIndex tmp = cacheHeap[a];
- cacheHeap[a] = cacheHeap[b];
- cacheHeap[b] = tmp;
-
- setValue(refInfo[set][cacheHeap[a]].addr, a);
- setValue(refInfo[set][cacheHeap[b]].addr, b);
- }
-
- int heapLeft(int index) { return index + index + 1; }
- int heapRight(int index) { return index + index + 2; }
- int heapParent(int index) { return (index - 1) >> 1; }
-
- RefIndex heapRank(int set, int index) {
- return refInfo[set][cacheHeap[index]].nextRefTime;
- }
-
- void heapify(int set, int start){
- int left = heapLeft(start);
- int right = heapRight(start);
- int max = start;
- if (left < assoc && heapRank(set, left) > heapRank(set, start)) {
- max = left;
- }
- if (right < assoc && heapRank(set, right) > heapRank(set, max)) {
- max = right;
- }
-
- if (max != start) {
- heapSwap(set, start, max);
- heapify(set, max);
- }
- }
-
- void verifyHeap(int set, int start) {
- int left = heapLeft(start);
- int right = heapRight(start);
-
- if (left < assoc) {
- assert(heapRank(set, start) >= heapRank(set, left));
- verifyHeap(set, left);
- }
- if (right < assoc) {
- assert(heapRank(set, start) >= heapRank(set, right));
- verifyHeap(set, right);
- }
- }
-
- void processRankIncrease(int set, int start) {
- int parent = heapParent(start);
- while (start > 0 && heapRank(set,parent) < heapRank(set,start)) {
- heapSwap(set, parent, start);
- start = parent;
- parent = heapParent(start);
- }
- }
-
- void processSet(int set);
-
- static const RefIndex InfiniteRef = 0x7fffffff;
-
- /** Memory reference trace. */
- MemTraceReader *trace;
-
- /** Cache heap for replacement. */
- std::vector<RefIndex> cacheHeap;
-
- /** The number of blocks in the cache. */
- const int numBlks;
-
- const int assoc;
- const int numSets;
- const int setMask;
-
-
- int misses;
- int hits;
-
- public:
- /**
- * Construct a OptCPU object.
- */
- OptCPU(const std::string &name,
- MemTraceReader *_trace,
- int block_size,
- int cache_size,
- int assoc);
-
- /**
- * Perform the optimal replacement simulation.
- */
- void tick();
-};
-
-#endif // __CPU_TRACE_OPT_CPU_HH__
diff --git a/cpu/trace/reader/ibm_reader.cc b/cpu/trace/reader/ibm_reader.cc
deleted file mode 100644
index 420101b63..000000000
--- a/cpu/trace/reader/ibm_reader.cc
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * Declaration of a IBM memory trace format reader.
- */
-#include <sstream>
-
-#include "cpu/trace/reader/ibm_reader.hh"
-#include "sim/builder.hh"
-#include "base/misc.hh" // for fatal
-
-using namespace std;
-
-IBMReader::IBMReader(const string &name, const string &filename)
- : MemTraceReader(name)
-{
- if (strcmp((filename.c_str() + filename.length() -3), ".gz") == 0) {
- // Compressed file, need to use a pipe to gzip.
- stringstream buf;
- buf << "gzip -d -c " << filename << endl;
- trace = popen(buf.str().c_str(), "r");
- } else {
- trace = fopen(filename.c_str(), "rb");
- }
- if (!trace) {
- fatal("Can't open file %s", filename);
- }
-}
-
-Tick
-IBMReader::getNextReq(MemReqPtr &req)
-{
- MemReqPtr tmp_req;
-
- int c = getc(trace);
- if (c != EOF) {
- tmp_req = new MemReq();
- //int cpu_id = (c & 0xf0) >> 4;
- int type = c & 0x0f;
- // We have L1 miss traces, so all accesses are 128 bytes
- tmp_req->size = 128;
-
- tmp_req->paddr = 0;
- for (int i = 2; i >= 0; --i) {
- c = getc(trace);
- if (c == EOF) {
- fatal("Unexpected end of file");
- }
- tmp_req->paddr |= ((c & 0xff) << (8 * i));
- }
- tmp_req->paddr = tmp_req->paddr << 7;
-
- switch(type) {
- case IBM_COND_EXCLUSIVE_FETCH:
- case IBM_READ_ONLY_FETCH:
- tmp_req->cmd = Read;
- break;
- case IBM_EXCLUSIVE_FETCH:
- case IBM_FETCH_NO_DATA:
- tmp_req->cmd = Write;
- break;
- case IBM_INST_FETCH:
- tmp_req->cmd = Read;
- break;
- default:
- fatal("Unknown trace entry type.");
- }
-
- }
- req = tmp_req;
- return 0;
-}
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(IBMReader)
-
- Param<string> filename;
-
-END_DECLARE_SIM_OBJECT_PARAMS(IBMReader)
-
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(IBMReader)
-
- INIT_PARAM(filename, "trace file")
-
-END_INIT_SIM_OBJECT_PARAMS(IBMReader)
-
-
-CREATE_SIM_OBJECT(IBMReader)
-{
- return new IBMReader(getInstanceName(), filename);
-}
-
-REGISTER_SIM_OBJECT("IBMReader", IBMReader)
diff --git a/cpu/trace/reader/ibm_reader.hh b/cpu/trace/reader/ibm_reader.hh
deleted file mode 100644
index ce29206a2..000000000
--- a/cpu/trace/reader/ibm_reader.hh
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * Definition of a IBM memory trace format reader.
- */
-
-#ifndef __IBM_READER_HH__
-#define __IBM_READER_HH__
-
-#include <stdio.h>
-#include "cpu/trace/reader/mem_trace_reader.hh"
-#include "mem/mem_req.hh"
-
-/**
- * A memory trace reader for the IBM memory trace format.
- */
-class IBMReader : public MemTraceReader
-{
- /** IBM trace file. */
- FILE* trace;
-
- enum IBMType {
- IBM_INST_FETCH,
- IBM_READ_ONLY_FETCH,
- IBM_COND_EXCLUSIVE_FETCH,
- IBM_EXCLUSIVE_FETCH,
- IBM_FETCH_NO_DATA
- };
-
- public:
- /**
- * Construct an IBMReader.
- */
- IBMReader(const std::string &name, const std::string &filename);
-
- /**
- * Read the next request from the trace. Returns the request in the
- * provided MemReqPtr and the cycle of the request in the return value.
- * @param req Return the next request from the trace.
- * @return IBM traces don't store timing information, return 0
- */
- virtual Tick getNextReq(MemReqPtr &req);
-};
-
-#endif //__IBM_READER_HH__
-
diff --git a/cpu/trace/reader/itx_reader.cc b/cpu/trace/reader/itx_reader.cc
deleted file mode 100644
index 39ba27393..000000000
--- a/cpu/trace/reader/itx_reader.cc
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * Declaration of a Intel ITX memory trace format reader.
- */
-#include <sstream>
-
-#include "cpu/trace/reader/itx_reader.hh"
-#include "sim/builder.hh"
-#include "base/misc.hh" // for fatal
-
-using namespace std;
-
-ITXReader::ITXReader(const string &name, const string &filename)
- : MemTraceReader(name)
-{
- if (strcmp((filename.c_str() + filename.length() -3), ".gz") == 0) {
- // Compressed file, need to use a pipe to gzip.
- stringstream buf;
- buf << "gzip -d -c " << filename << endl;
- trace = popen(buf.str().c_str(), "r");
- } else {
- trace = fopen(filename.c_str(), "rb");
- }
- if (!trace) {
- fatal("Can't open file %s", filename);
- }
- traceFormat = 0;
- int c;
- for (int i = 0; i < 4; ++i) {
- c = getc(trace);
- if (c == EOF) {
- fatal("Unexpected end of trace file.");
- }
- traceFormat |= (c & 0xff) << (8 * i);
- }
- if (traceFormat > 2)
- fatal("Invalid trace format.");
-}
-
-Tick
-ITXReader::getNextReq(MemReqPtr &req)
-{
- MemReqPtr tmp_req = new MemReq();
- bool phys_val;
- do {
- int c = getc(trace);
- if (c != EOF) {
- // Decode first byte
- // phys_val<1> | type <2:0> | size <3:0>
- phys_val = c & 0x80;
- tmp_req->size = (c & 0x0f) + 1;
- int type = (c & 0x70) >> 4;
-
- // Could be a compressed instruction entry, expand if necessary
- if (type == ITXCodeComp) {
- if (traceFormat != 2) {
- fatal("Compressed code entry in non CompCode trace.");
- }
- if (!codeVirtValid) {
- fatal("Corrupt CodeComp entry.");
- }
-
- tmp_req->vaddr = codeVirtAddr;
- codeVirtAddr += tmp_req->size;
- if (phys_val) {
- if (!codePhysValid) {
- fatal("Corrupt CodeComp entry.");
- }
- tmp_req->paddr = codePhysAddr;
- if (((tmp_req->paddr & 0xfff) + tmp_req->size) & ~0xfff) {
- // Crossed page boundary, next physical address is
- // invalid
- codePhysValid = false;
- } else {
- codePhysAddr += tmp_req->size;
- }
- assert(tmp_req->paddr >> 36 == 0);
- } else {
- codePhysValid = false;
- }
- type = ITXCode;
- tmp_req->cmd = Read;
- } else {
- // Normal entry
- tmp_req->vaddr = 0;
- for (int i = 0; i < 4; ++i) {
- c = getc(trace);
- if (c == EOF) {
- fatal("Unexpected end of trace file.");
- }
- tmp_req->vaddr |= (c & 0xff) << (8 * i);
- }
- if (type == ITXCode) {
- codeVirtAddr = tmp_req->vaddr + tmp_req->size;
- codeVirtValid = true;
- }
- tmp_req->paddr = 0;
- if (phys_val) {
- c = getc(trace);
- if (c == EOF) {
- fatal("Unexpected end of trace file.");
- }
- // Get the page offset from the virtual address.
- tmp_req->paddr = tmp_req->vaddr & 0xfff;
- tmp_req->paddr |= (c & 0xf0) << 8;
- tmp_req->paddr |= (Addr)(c & 0x0f) << 32;
- for (int i = 2; i < 4; ++i) {
- c = getc(trace);
- if (c == EOF) {
- fatal("Unexpected end of trace file.");
- }
- tmp_req->paddr |= (Addr)(c & 0xff) << (8 * i);
- }
- if (type == ITXCode) {
- if (((tmp_req->paddr & 0xfff) + tmp_req->size)
- & ~0xfff) {
- // Crossing the page boundary, next physical
- // address isn't valid
- codePhysValid = false;
- } else {
- codePhysAddr = tmp_req->paddr + tmp_req->size;
- codePhysValid = true;
- }
- }
- assert(tmp_req->paddr >> 36 == 0);
- } else if (type == ITXCode) {
- codePhysValid = false;
- }
- switch(type) {
- case ITXRead:
- tmp_req->cmd = Read;
- break;
- case ITXWrite:
- tmp_req->cmd = Write;
- break;
- case ITXWriteback:
- tmp_req->cmd = Writeback;
- break;
- case ITXCode:
- tmp_req->cmd = Read;
- tmp_req->flags |= INST_READ;
- break;
- default:
- fatal("Unknown ITX type");
- }
- }
- } else {
- // EOF need to return a null request
- MemReqPtr null_req;
- req = null_req;
- return 0;
- }
- } while (!phys_val);
- req = tmp_req;
- assert(!req || (req->paddr >> 36) == 0);
- return 0;
-}
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITXReader)
-
- Param<string> filename;
-
-END_DECLARE_SIM_OBJECT_PARAMS(ITXReader)
-
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(ITXReader)
-
- INIT_PARAM(filename, "trace file")
-
-END_INIT_SIM_OBJECT_PARAMS(ITXReader)
-
-
-CREATE_SIM_OBJECT(ITXReader)
-{
- return new ITXReader(getInstanceName(), filename);
-}
-
-REGISTER_SIM_OBJECT("ITXReader", ITXReader)
diff --git a/cpu/trace/reader/itx_reader.hh b/cpu/trace/reader/itx_reader.hh
deleted file mode 100644
index a16a08085..000000000
--- a/cpu/trace/reader/itx_reader.hh
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * Definition of a Intel ITX memory trace format reader.
- */
-
-#ifndef __ITX_READER_HH__
-#define __ITX_READER_HH__
-
-#include <stdio.h>
-#include <string>
-
-#include "cpu/trace/reader/mem_trace_reader.hh"
-#include "mem/mem_req.hh"
-
-
-/**
- * A memory trace reader for the Intel ITX memory trace format.
- */
-class ITXReader : public MemTraceReader
-{
- private:
- /** Trace file. */
- FILE *trace;
-
- bool codeVirtValid;
- Addr codeVirtAddr;
- bool codePhysValid;
- Addr codePhysAddr;
-
- int traceFormat;
-
- enum ITXType {
- ITXRead,
- ITXWrite,
- ITXWriteback,
- ITXCode,
- ITXCodeComp
- };
-
- public:
- /**
- * Construct an ITXReader.
- */
- ITXReader(const std::string &name, const std::string &filename);
-
- /**
- * Read the next request from the trace. Returns the request in the
- * provided MemReqPtr and the cycle of the request in the return value.
- * @param req Return the next request from the trace.
- * @return ITX traces don't store timing information, return 0
- */
- virtual Tick getNextReq(MemReqPtr &req);
-};
-
-#endif //__ITX_READER_HH__
-
diff --git a/cpu/trace/reader/m5_reader.cc b/cpu/trace/reader/m5_reader.cc
deleted file mode 100644
index ce44672f2..000000000
--- a/cpu/trace/reader/m5_reader.cc
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * Declaration of a memory trace reader for a M5 memory trace.
- */
-
-#include "cpu/trace/reader/m5_reader.hh"
-#include "mem/trace/m5_format.hh"
-#include "mem/mem_cmd.hh"
-#include "sim/builder.hh"
-
-using namespace std;
-
-M5Reader::M5Reader(const string &name, const string &filename)
- : MemTraceReader(name)
-{
- traceFile.open(filename.c_str(), ios::binary);
-}
-
-Tick
-M5Reader::getNextReq(MemReqPtr &req)
-{
- M5Format ref;
-
- MemReqPtr tmp_req;
- // Need to read EOF char before eof() will return true.
- traceFile.read((char*) &ref, sizeof(ref));
- if (!traceFile.eof()) {
- //traceFile.read((char*) &ref, sizeof(ref));
-#ifndef NDEBUG
- int gcount = traceFile.gcount();
- assert(gcount != 0 || traceFile.eof());
- assert(gcount == sizeof(ref));
- assert(ref.cmd < 12);
-#endif
- tmp_req = new MemReq();
- tmp_req->paddr = ref.paddr;
- tmp_req->asid = ref.asid;
- // Assume asid == thread_num
- tmp_req->thread_num = ref.asid;
- tmp_req->cmd = (MemCmdEnum)ref.cmd;
- tmp_req->size = ref.size;
- tmp_req->dest = ref.dest;
- } else {
- ref.cycle = 0;
- }
- req = tmp_req;
- return ref.cycle;
-}
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(M5Reader)
-
- Param<string> filename;
-
-END_DECLARE_SIM_OBJECT_PARAMS(M5Reader)
-
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(M5Reader)
-
- INIT_PARAM(filename, "trace file")
-
-END_INIT_SIM_OBJECT_PARAMS(M5Reader)
-
-
-CREATE_SIM_OBJECT(M5Reader)
-{
- return new M5Reader(getInstanceName(), filename);
-}
-
-REGISTER_SIM_OBJECT("M5Reader", M5Reader)
diff --git a/cpu/trace/reader/m5_reader.hh b/cpu/trace/reader/m5_reader.hh
deleted file mode 100644
index 974a83ffa..000000000
--- a/cpu/trace/reader/m5_reader.hh
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * Definition of a memory trace reader for a M5 memory trace.
- */
-
-#ifndef __M5_READER_HH__
-#define __M5_READER_HH__
-
-#include <fstream>
-
-#include "cpu/trace/reader/mem_trace_reader.hh"
-
-/**
- * A memory trace reader for an M5 memory trace. @sa M5Writer.
- */
-class M5Reader : public MemTraceReader
-{
- /** The traceFile. */
- std::ifstream traceFile;
-
- std::string fn;
-
- public:
- /**
- * Construct an M5 memory trace reader.
- */
- M5Reader(const std::string &name, const std::string &filename);
-
-
- /**
- * Read the next request from the trace. Returns the request in the
- * provided MemReqPtr and the cycle of the request in the return value.
- * @param req Return the next request from the trace.
- * @return The cycle the reference was started.
- */
- virtual Tick getNextReq(MemReqPtr &req);
-};
-
-#endif // __M5_READER_HH__
diff --git a/cpu/trace/reader/mem_trace_reader.cc b/cpu/trace/reader/mem_trace_reader.cc
deleted file mode 100644
index 769f0be27..000000000
--- a/cpu/trace/reader/mem_trace_reader.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * SimObject Declaration of pure virtual MemTraceReader class.
- */
-
-#include "cpu/trace/reader/mem_trace_reader.hh"
-#include "sim/param.hh"
-
-DEFINE_SIM_OBJECT_CLASS_NAME("MemTraceReader", MemTraceReader);
diff --git a/cpu/trace/reader/mem_trace_reader.hh b/cpu/trace/reader/mem_trace_reader.hh
deleted file mode 100644
index b433cdbdd..000000000
--- a/cpu/trace/reader/mem_trace_reader.hh
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * Definitions for a pure virtual interface to a memory trace reader.
- */
-
-#ifndef __MEM_TRACE_READER_HH__
-#define __MEM_TRACE_READER_HH__
-
-#include "sim/sim_object.hh"
-#include "mem/mem_req.hh" // For MemReqPtr
-
-/**
- * Pure virtual base class for memory trace readers.
- */
-class MemTraceReader : public SimObject
-{
- public:
- /** Construct this MemoryTrace reader. */
- MemTraceReader(const std::string &name) : SimObject(name) {}
-
- /**
- * Read the next request from the trace. Returns the request in the
- * provided MemReqPtr and the cycle of the request in the return value.
- * @param req Return the next request from the trace.
- * @return The cycle of the request, 0 if none in trace.
- */
- virtual Tick getNextReq(MemReqPtr &req) = 0;
-};
-
-#endif //__MEM_TRACE_READER_HH__
diff --git a/cpu/trace/trace_cpu.cc b/cpu/trace/trace_cpu.cc
deleted file mode 100644
index 20d0a567f..000000000
--- a/cpu/trace/trace_cpu.cc
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * Declaration of a memory trace CPU object. Uses a memory trace to drive the
- * provided memory hierarchy.
- */
-
-#include <algorithm> // For min
-
-#include "cpu/trace/trace_cpu.hh"
-#include "cpu/trace/reader/mem_trace_reader.hh"
-#include "mem/base_mem.hh" // For PARAM constructor
-#include "mem/mem_interface.hh"
-#include "sim/builder.hh"
-#include "sim/sim_events.hh"
-
-using namespace std;
-
-TraceCPU::TraceCPU(const string &name,
- MemInterface *icache_interface,
- MemInterface *dcache_interface,
- MemTraceReader *data_trace)
- : SimObject(name), icacheInterface(icache_interface),
- dcacheInterface(dcache_interface),
- dataTrace(data_trace), outstandingRequests(0), tickEvent(this)
-{
- assert(dcacheInterface);
- nextCycle = dataTrace->getNextReq(nextReq);
- tickEvent.schedule(0);
-}
-
-void
-TraceCPU::tick()
-{
- assert(outstandingRequests >= 0);
- assert(outstandingRequests < 1000);
- int instReqs = 0;
- int dataReqs = 0;
-
- while (nextReq && curTick >= nextCycle) {
- assert(nextReq->thread_num < 4 && "Not enough threads");
- if (nextReq->isInstRead() && icacheInterface) {
- if (icacheInterface->isBlocked())
- break;
-
- nextReq->time = curTick;
- if (nextReq->cmd == Squash) {
- icacheInterface->squash(nextReq->asid);
- } else {
- ++instReqs;
- if (icacheInterface->doEvents()) {
- nextReq->completionEvent =
- new TraceCompleteEvent(nextReq, this);
- icacheInterface->access(nextReq);
- } else {
- icacheInterface->access(nextReq);
- completeRequest(nextReq);
- }
- }
- } else {
- if (dcacheInterface->isBlocked())
- break;
-
- ++dataReqs;
- nextReq->time = curTick;
- if (dcacheInterface->doEvents()) {
- nextReq->completionEvent =
- new TraceCompleteEvent(nextReq, this);
- dcacheInterface->access(nextReq);
- } else {
- dcacheInterface->access(nextReq);
- completeRequest(nextReq);
- }
-
- }
- nextCycle = dataTrace->getNextReq(nextReq);
- }
-
- if (!nextReq) {
- // No more requests to send. Finish trailing events and exit.
- if (mainEventQueue.empty()) {
- new SimExitEvent("Finshed Memory Trace");
- } else {
- tickEvent.schedule(mainEventQueue.nextEventTime() + cycles(1));
- }
- } else {
- tickEvent.schedule(max(curTick + cycles(1), nextCycle));
- }
-}
-
-void
-TraceCPU::completeRequest(MemReqPtr& req)
-{
-}
-
-void
-TraceCompleteEvent::process()
-{
- tester->completeRequest(req);
-}
-
-const char *
-TraceCompleteEvent::description()
-{
- return "trace access complete";
-}
-
-TraceCPU::TickEvent::TickEvent(TraceCPU *c)
- : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
-{
-}
-
-void
-TraceCPU::TickEvent::process()
-{
- cpu->tick();
-}
-
-const char *
-TraceCPU::TickEvent::description()
-{
- return "TraceCPU tick event";
-}
-
-
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(TraceCPU)
-
- SimObjectParam<BaseMem *> icache;
- SimObjectParam<BaseMem *> dcache;
- SimObjectParam<MemTraceReader *> data_trace;
-
-END_DECLARE_SIM_OBJECT_PARAMS(TraceCPU)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(TraceCPU)
-
- INIT_PARAM_DFLT(icache, "instruction cache", NULL),
- INIT_PARAM_DFLT(dcache, "data cache", NULL),
- INIT_PARAM_DFLT(data_trace, "data trace", NULL)
-
-END_INIT_SIM_OBJECT_PARAMS(TraceCPU)
-
-CREATE_SIM_OBJECT(TraceCPU)
-{
- return new TraceCPU(getInstanceName(),
- (icache) ? icache->getInterface() : NULL,
- (dcache) ? dcache->getInterface() : NULL,
- data_trace);
-}
-
-REGISTER_SIM_OBJECT("TraceCPU", TraceCPU)
-
diff --git a/cpu/trace/trace_cpu.hh b/cpu/trace/trace_cpu.hh
deleted file mode 100644
index 69ca35321..000000000
--- a/cpu/trace/trace_cpu.hh
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * Declaration of a memory trace CPU object. Uses a memory trace to drive the
- * provided memory hierarchy.
- */
-
-#ifndef __CPU_TRACE_TRACE_CPU_HH__
-#define __CPU_TRACE_TRACE_CPU_HH__
-
-#include <string>
-
-#include "mem/mem_req.hh" // for MemReqPtr
-#include "sim/eventq.hh" // for Event
-#include "sim/sim_object.hh"
-
-// Forward declaration.
-class MemInterface;
-class MemTraceReader;
-
-/**
- * A cpu object for running memory traces through a memory hierarchy.
- */
-class TraceCPU : public SimObject
-{
- private:
- /** Interface for instruction trace requests, if any. */
- MemInterface *icacheInterface;
- /** Interface for data trace requests, if any. */
- MemInterface *dcacheInterface;
-
- /** Data reference trace. */
- MemTraceReader *dataTrace;
-
- /** Number of outstanding requests. */
- int outstandingRequests;
-
- /** Cycle of the next request, 0 if not available. */
- Tick nextCycle;
-
- /** Next request. */
- MemReqPtr nextReq;
-
- /**
- * Event to call the TraceCPU::tick
- */
- class TickEvent : public Event
- {
- private:
- /** The associated CPU */
- TraceCPU *cpu;
-
- public:
- /**
- * Construct this event;
- */
- TickEvent(TraceCPU *c);
-
- /**
- * Call the tick function.
- */
- void process();
-
- /**
- * Return a string description of this event.
- */
- const char *description();
- };
-
- TickEvent tickEvent;
-
- public:
- /**
- * Construct a TraceCPU object.
- */
- TraceCPU(const std::string &name,
- MemInterface *icache_interface,
- MemInterface *dcache_interface,
- MemTraceReader *data_trace);
-
- inline Tick cycles(int numCycles) { return numCycles; }
-
- /**
- * Perform all the accesses for one cycle.
- */
- void tick();
-
- /**
- * Handle a completed memory request.
- */
- void completeRequest(MemReqPtr &req);
-};
-
-class TraceCompleteEvent : public Event
-{
- MemReqPtr req;
- TraceCPU *tester;
-
- public:
-
- TraceCompleteEvent(MemReqPtr &_req, TraceCPU *_tester)
- : Event(&mainEventQueue), req(_req), tester(_tester)
- {
- setFlags(AutoDelete);
- }
-
- void process();
-
- virtual const char *description();
-};
-
-#endif // __CPU_TRACE_TRACE_CPU_HH__
-