thread_context_impl.hh revision 12109
14120Sgblack@eecs.umich.edu/*
24120Sgblack@eecs.umich.edu * Copyright (c) 2010-2012, 2016 ARM Limited
34120Sgblack@eecs.umich.edu * Copyright (c) 2013 Advanced Micro Devices, Inc.
44120Sgblack@eecs.umich.edu * All rights reserved
54120Sgblack@eecs.umich.edu *
64120Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall
74120Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual
84120Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating
94120Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software
104120Sgblack@eecs.umich.edu * licensed hereunder.  You may use the software subject to the license
114120Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated
124120Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software,
134120Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form.
144120Sgblack@eecs.umich.edu *
154120Sgblack@eecs.umich.edu * Copyright (c) 2004-2006 The Regents of The University of Michigan
164120Sgblack@eecs.umich.edu * All rights reserved.
174120Sgblack@eecs.umich.edu *
184120Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
194120Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
204120Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
214120Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
224120Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
234120Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
244120Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
254120Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
264120Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
274120Sgblack@eecs.umich.edu * this software without specific prior written permission.
284120Sgblack@eecs.umich.edu *
294120Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
304120Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
314120Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
324120Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
334120Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
344120Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
354120Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
364120Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
374120Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
384120Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
394120Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
404120Sgblack@eecs.umich.edu *
414120Sgblack@eecs.umich.edu * Authors: Kevin Lim
424120Sgblack@eecs.umich.edu *          Korey Sewell
434120Sgblack@eecs.umich.edu */
444120Sgblack@eecs.umich.edu
454120Sgblack@eecs.umich.edu#ifndef __CPU_O3_THREAD_CONTEXT_IMPL_HH__
464120Sgblack@eecs.umich.edu#define __CPU_O3_THREAD_CONTEXT_IMPL_HH__
474120Sgblack@eecs.umich.edu
484120Sgblack@eecs.umich.edu#include "arch/kernel_stats.hh"
494120Sgblack@eecs.umich.edu#include "arch/registers.hh"
504120Sgblack@eecs.umich.edu#include "config/the_isa.hh"
514120Sgblack@eecs.umich.edu#include "cpu/o3/thread_context.hh"
524120Sgblack@eecs.umich.edu#include "cpu/quiesce_event.hh"
534120Sgblack@eecs.umich.edu#include "debug/O3CPU.hh"
544120Sgblack@eecs.umich.edu
554120Sgblack@eecs.umich.edutemplate <class Impl>
564120Sgblack@eecs.umich.eduFSTranslatingPortProxy&
574120Sgblack@eecs.umich.eduO3ThreadContext<Impl>::getVirtProxy()
584120Sgblack@eecs.umich.edu{
594120Sgblack@eecs.umich.edu    return thread->getVirtProxy();
604120Sgblack@eecs.umich.edu}
614139Sgblack@eecs.umich.edu
624135Sgblack@eecs.umich.edutemplate <class Impl>
634120Sgblack@eecs.umich.eduvoid
644120Sgblack@eecs.umich.eduO3ThreadContext<Impl>::dumpFuncProfile()
654120Sgblack@eecs.umich.edu{
665114Sgblack@eecs.umich.edu    thread->dumpFuncProfile();
675114Sgblack@eecs.umich.edu}
684135Sgblack@eecs.umich.edu
694365Sgblack@eecs.umich.edutemplate <class Impl>
705114Sgblack@eecs.umich.eduvoid
715114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::takeOverFrom(ThreadContext *old_context)
725139Sgblack@eecs.umich.edu{
735114Sgblack@eecs.umich.edu    ::takeOverFrom(*this, *old_context);
745139Sgblack@eecs.umich.edu    TheISA::Decoder *newDecoder = getDecoderPtr();
755139Sgblack@eecs.umich.edu    TheISA::Decoder *oldDecoder = old_context->getDecoderPtr();
765139Sgblack@eecs.umich.edu    newDecoder->takeOverFrom(oldDecoder);
775114Sgblack@eecs.umich.edu
785114Sgblack@eecs.umich.edu    thread->kernelStats = old_context->getKernelStats();
795114Sgblack@eecs.umich.edu    thread->funcExeInst = old_context->readFuncExeInst();
804729Sgblack@eecs.umich.edu
814365Sgblack@eecs.umich.edu    thread->noSquashFromTC = false;
825114Sgblack@eecs.umich.edu    thread->trapPending = false;
834365Sgblack@eecs.umich.edu}
844365Sgblack@eecs.umich.edu
855114Sgblack@eecs.umich.edutemplate <class Impl>
865114Sgblack@eecs.umich.eduvoid
875114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::activate()
885114Sgblack@eecs.umich.edu{
895114Sgblack@eecs.umich.edu    DPRINTF(O3CPU, "Calling activate on Thread Context %d\n",
905114Sgblack@eecs.umich.edu            threadId());
915114Sgblack@eecs.umich.edu
925114Sgblack@eecs.umich.edu    if (thread->status() == ThreadContext::Active)
935114Sgblack@eecs.umich.edu        return;
945114Sgblack@eecs.umich.edu
955114Sgblack@eecs.umich.edu    thread->lastActivate = curTick();
965114Sgblack@eecs.umich.edu    thread->setStatus(ThreadContext::Active);
975114Sgblack@eecs.umich.edu
985114Sgblack@eecs.umich.edu    // status() == Suspended
995114Sgblack@eecs.umich.edu    cpu->activateContext(thread->threadId());
1005114Sgblack@eecs.umich.edu}
1015139Sgblack@eecs.umich.edu
1025139Sgblack@eecs.umich.edutemplate <class Impl>
1035139Sgblack@eecs.umich.eduvoid
1045114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::suspend()
1055114Sgblack@eecs.umich.edu{
1065114Sgblack@eecs.umich.edu    DPRINTF(O3CPU, "Calling suspend on Thread Context %d\n",
1075114Sgblack@eecs.umich.edu            threadId());
1085114Sgblack@eecs.umich.edu
1095114Sgblack@eecs.umich.edu    if (thread->status() == ThreadContext::Suspended)
1105114Sgblack@eecs.umich.edu        return;
1115114Sgblack@eecs.umich.edu
1125139Sgblack@eecs.umich.edu    thread->lastActivate = curTick();
1135139Sgblack@eecs.umich.edu    thread->lastSuspend = curTick();
1145139Sgblack@eecs.umich.edu
1155114Sgblack@eecs.umich.edu    thread->setStatus(ThreadContext::Suspended);
1165114Sgblack@eecs.umich.edu    cpu->suspendContext(thread->threadId());
1175114Sgblack@eecs.umich.edu}
1185124Sgblack@eecs.umich.edu
1195114Sgblack@eecs.umich.edutemplate <class Impl>
1205114Sgblack@eecs.umich.eduvoid
1215114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::halt()
1225114Sgblack@eecs.umich.edu{
1235114Sgblack@eecs.umich.edu    DPRINTF(O3CPU, "Calling halt on Thread Context %d\n", threadId());
1245114Sgblack@eecs.umich.edu
1255114Sgblack@eecs.umich.edu    if (thread->status() == ThreadContext::Halted)
1265139Sgblack@eecs.umich.edu        return;
1275139Sgblack@eecs.umich.edu
1285139Sgblack@eecs.umich.edu    thread->setStatus(ThreadContext::Halted);
1295114Sgblack@eecs.umich.edu    cpu->haltContext(thread->threadId());
1305114Sgblack@eecs.umich.edu}
1315114Sgblack@eecs.umich.edu
1325124Sgblack@eecs.umich.edutemplate <class Impl>
1335114Sgblack@eecs.umich.eduvoid
1345114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::regStats(const std::string &name)
1355114Sgblack@eecs.umich.edu{
1365114Sgblack@eecs.umich.edu    if (FullSystem) {
1375114Sgblack@eecs.umich.edu        thread->kernelStats = new TheISA::Kernel::Statistics(cpu->system);
1385114Sgblack@eecs.umich.edu        thread->kernelStats->regStats(name + ".kern");
1395114Sgblack@eecs.umich.edu    }
1405139Sgblack@eecs.umich.edu}
1415139Sgblack@eecs.umich.edu
1425139Sgblack@eecs.umich.edutemplate <class Impl>
1435114Sgblack@eecs.umich.eduTick
1445114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::readLastActivate()
1455114Sgblack@eecs.umich.edu{
1465124Sgblack@eecs.umich.edu    return thread->lastActivate;
1475114Sgblack@eecs.umich.edu}
1484135Sgblack@eecs.umich.edu
1494150Sgblack@eecs.umich.edutemplate <class Impl>
1504365Sgblack@eecs.umich.eduTick
1514365Sgblack@eecs.umich.eduO3ThreadContext<Impl>::readLastSuspend()
1524365Sgblack@eecs.umich.edu{
1534729Sgblack@eecs.umich.edu    return thread->lastSuspend;
1544365Sgblack@eecs.umich.edu}
1554365Sgblack@eecs.umich.edu
1564365Sgblack@eecs.umich.edutemplate <class Impl>
1574365Sgblack@eecs.umich.eduvoid
1584365Sgblack@eecs.umich.eduO3ThreadContext<Impl>::profileClear()
1594365Sgblack@eecs.umich.edu{
1604365Sgblack@eecs.umich.edu    thread->profileClear();
1614365Sgblack@eecs.umich.edu}
1624365Sgblack@eecs.umich.edu
1634365Sgblack@eecs.umich.edutemplate <class Impl>
1644150Sgblack@eecs.umich.eduvoid
1654150Sgblack@eecs.umich.eduO3ThreadContext<Impl>::profileSample()
1664150Sgblack@eecs.umich.edu{
1674150Sgblack@eecs.umich.edu    thread->profileSample();
1685114Sgblack@eecs.umich.edu}
1695114Sgblack@eecs.umich.edu
1705114Sgblack@eecs.umich.edutemplate <class Impl>
1715114Sgblack@eecs.umich.eduvoid
1725114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc)
1735114Sgblack@eecs.umich.edu{
1745114Sgblack@eecs.umich.edu    // Prevent squashing
1755114Sgblack@eecs.umich.edu    thread->noSquashFromTC = true;
1765114Sgblack@eecs.umich.edu    TheISA::copyRegs(tc, this);
1775114Sgblack@eecs.umich.edu    thread->noSquashFromTC = false;
1785114Sgblack@eecs.umich.edu
1795114Sgblack@eecs.umich.edu    if (!FullSystem)
1805114Sgblack@eecs.umich.edu        this->thread->funcExeInst = tc->readFuncExeInst();
1815114Sgblack@eecs.umich.edu}
1825114Sgblack@eecs.umich.edu
1835114Sgblack@eecs.umich.edutemplate <class Impl>
1845114Sgblack@eecs.umich.eduvoid
1855114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::clearArchRegs()
1865114Sgblack@eecs.umich.edu{
1875114Sgblack@eecs.umich.edu    cpu->isa[thread->threadId()]->clear();
1885114Sgblack@eecs.umich.edu}
1895114Sgblack@eecs.umich.edu
1905114Sgblack@eecs.umich.edutemplate <class Impl>
1915114Sgblack@eecs.umich.eduuint64_t
1925114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::readIntRegFlat(int reg_idx)
1935114Sgblack@eecs.umich.edu{
1945114Sgblack@eecs.umich.edu    return cpu->readArchIntReg(reg_idx, thread->threadId());
1955114Sgblack@eecs.umich.edu}
1965114Sgblack@eecs.umich.edu
1975114Sgblack@eecs.umich.edutemplate <class Impl>
1985114Sgblack@eecs.umich.eduTheISA::FloatReg
1995114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::readFloatRegFlat(int reg_idx)
2005114Sgblack@eecs.umich.edu{
2015114Sgblack@eecs.umich.edu    return cpu->readArchFloatReg(reg_idx, thread->threadId());
2025114Sgblack@eecs.umich.edu}
2035114Sgblack@eecs.umich.edu
2045114Sgblack@eecs.umich.edutemplate <class Impl>
2055114Sgblack@eecs.umich.eduTheISA::FloatRegBits
2065114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::readFloatRegBitsFlat(int reg_idx)
2075114Sgblack@eecs.umich.edu{
2085114Sgblack@eecs.umich.edu    return cpu->readArchFloatRegInt(reg_idx, thread->threadId());
2095114Sgblack@eecs.umich.edu}
2105114Sgblack@eecs.umich.edu
2115114Sgblack@eecs.umich.edutemplate <class Impl>
2125114Sgblack@eecs.umich.educonst TheISA::VecRegContainer&
2135114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::readVecRegFlat(int reg_id) const
2145114Sgblack@eecs.umich.edu{
2155114Sgblack@eecs.umich.edu    return cpu->readArchVecReg(reg_id, thread->threadId());
2165114Sgblack@eecs.umich.edu}
2175114Sgblack@eecs.umich.edu
2185114Sgblack@eecs.umich.edutemplate <class Impl>
2195114Sgblack@eecs.umich.eduTheISA::VecRegContainer&
2205114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::getWritableVecRegFlat(int reg_id)
2215114Sgblack@eecs.umich.edu{
2225114Sgblack@eecs.umich.edu    return cpu->getWritableArchVecReg(reg_id, thread->threadId());
2235114Sgblack@eecs.umich.edu}
2245114Sgblack@eecs.umich.edu
2255114Sgblack@eecs.umich.edutemplate <class Impl>
2265114Sgblack@eecs.umich.educonst TheISA::VecElem&
2275114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::readVecElemFlat(const RegIndex& idx,
2285114Sgblack@eecs.umich.edu                                           const ElemIndex& elemIndex) const
2295114Sgblack@eecs.umich.edu{
2305114Sgblack@eecs.umich.edu    return cpu->readArchVecElem(idx, elemIndex, thread->threadId());
2315114Sgblack@eecs.umich.edu}
2325114Sgblack@eecs.umich.edu
2335114Sgblack@eecs.umich.edutemplate <class Impl>
2345114Sgblack@eecs.umich.eduTheISA::CCReg
2355114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::readCCRegFlat(int reg_idx)
2365114Sgblack@eecs.umich.edu{
2375114Sgblack@eecs.umich.edu    return cpu->readArchCCReg(reg_idx, thread->threadId());
2385114Sgblack@eecs.umich.edu}
2395114Sgblack@eecs.umich.edu
2405114Sgblack@eecs.umich.edutemplate <class Impl>
2415114Sgblack@eecs.umich.eduvoid
2425114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::setIntRegFlat(int reg_idx, uint64_t val)
2435114Sgblack@eecs.umich.edu{
2445114Sgblack@eecs.umich.edu    cpu->setArchIntReg(reg_idx, val, thread->threadId());
2455114Sgblack@eecs.umich.edu
2465114Sgblack@eecs.umich.edu    conditionalSquash();
2475114Sgblack@eecs.umich.edu}
2485114Sgblack@eecs.umich.edu
2495114Sgblack@eecs.umich.edutemplate <class Impl>
2505114Sgblack@eecs.umich.eduvoid
2515114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::setFloatRegFlat(int reg_idx, FloatReg val)
2525114Sgblack@eecs.umich.edu{
2535114Sgblack@eecs.umich.edu    cpu->setArchFloatReg(reg_idx, val, thread->threadId());
2545114Sgblack@eecs.umich.edu
2555114Sgblack@eecs.umich.edu    conditionalSquash();
2565114Sgblack@eecs.umich.edu}
2575114Sgblack@eecs.umich.edu
2585114Sgblack@eecs.umich.edutemplate <class Impl>
2595114Sgblack@eecs.umich.eduvoid
2605114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::setFloatRegBitsFlat(int reg_idx, FloatRegBits val)
2615114Sgblack@eecs.umich.edu{
2625114Sgblack@eecs.umich.edu    cpu->setArchFloatRegInt(reg_idx, val, thread->threadId());
2635114Sgblack@eecs.umich.edu
2645114Sgblack@eecs.umich.edu    conditionalSquash();
2655114Sgblack@eecs.umich.edu}
2665114Sgblack@eecs.umich.edu
2675114Sgblack@eecs.umich.edutemplate <class Impl>
2685114Sgblack@eecs.umich.eduvoid
2695114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::setVecRegFlat(int reg_idx, const VecRegContainer& val)
2705114Sgblack@eecs.umich.edu{
2715114Sgblack@eecs.umich.edu    cpu->setArchVecReg(reg_idx, val, thread->threadId());
2725114Sgblack@eecs.umich.edu
2735114Sgblack@eecs.umich.edu    conditionalSquash();
2745114Sgblack@eecs.umich.edu}
2755114Sgblack@eecs.umich.edu
2765114Sgblack@eecs.umich.edutemplate <class Impl>
2775114Sgblack@eecs.umich.eduvoid
2785114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::setVecElemFlat(const RegIndex& idx,
2795114Sgblack@eecs.umich.edu        const ElemIndex& elemIndex, const VecElem& val)
2805114Sgblack@eecs.umich.edu{
2815114Sgblack@eecs.umich.edu    cpu->setArchVecElem(idx, elemIndex, val, thread->threadId());
2825114Sgblack@eecs.umich.edu    conditionalSquash();
2835114Sgblack@eecs.umich.edu}
2845114Sgblack@eecs.umich.edu
2855114Sgblack@eecs.umich.edutemplate <class Impl>
2865114Sgblack@eecs.umich.eduvoid
2875114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::setCCRegFlat(int reg_idx, TheISA::CCReg val)
2885114Sgblack@eecs.umich.edu{
2895114Sgblack@eecs.umich.edu    cpu->setArchCCReg(reg_idx, val, thread->threadId());
2905114Sgblack@eecs.umich.edu
2915114Sgblack@eecs.umich.edu    conditionalSquash();
2925114Sgblack@eecs.umich.edu}
2935114Sgblack@eecs.umich.edu
2945114Sgblack@eecs.umich.edutemplate <class Impl>
2955114Sgblack@eecs.umich.eduvoid
2965114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::pcState(const TheISA::PCState &val)
2975114Sgblack@eecs.umich.edu{
2985114Sgblack@eecs.umich.edu    cpu->pcState(val, thread->threadId());
2995139Sgblack@eecs.umich.edu
3005139Sgblack@eecs.umich.edu    conditionalSquash();
3015114Sgblack@eecs.umich.edu}
3025114Sgblack@eecs.umich.edu
3035114Sgblack@eecs.umich.edutemplate <class Impl>
3045114Sgblack@eecs.umich.eduvoid
3055114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::pcStateNoRecord(const TheISA::PCState &val)
3065114Sgblack@eecs.umich.edu{
3075114Sgblack@eecs.umich.edu    cpu->pcState(val, thread->threadId());
3085114Sgblack@eecs.umich.edu
3095114Sgblack@eecs.umich.edu    conditionalSquash();
3105114Sgblack@eecs.umich.edu}
3115114Sgblack@eecs.umich.edu
3125114Sgblack@eecs.umich.edutemplate <class Impl>
3135114Sgblack@eecs.umich.eduRegId
3145114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::flattenRegId(const RegId& regId) const
3155114Sgblack@eecs.umich.edu{
3165114Sgblack@eecs.umich.edu    return cpu->isa[thread->threadId()]->flattenRegId(regId);
3175114Sgblack@eecs.umich.edu}
3185114Sgblack@eecs.umich.edu
3195114Sgblack@eecs.umich.edutemplate <class Impl>
3205652Sgblack@eecs.umich.eduvoid
3215114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::setMiscRegNoEffect(int misc_reg, const MiscReg &val)
3225114Sgblack@eecs.umich.edu{
3235114Sgblack@eecs.umich.edu    cpu->setMiscRegNoEffect(misc_reg, val, thread->threadId());
3245114Sgblack@eecs.umich.edu
3255114Sgblack@eecs.umich.edu    conditionalSquash();
3265114Sgblack@eecs.umich.edu}
3275114Sgblack@eecs.umich.edu
3285652Sgblack@eecs.umich.edu#endif//__CPU_O3_THREAD_CONTEXT_IMPL_HH__
3295114Sgblack@eecs.umich.edutemplate <class Impl>
3305114Sgblack@eecs.umich.eduvoid
3315114Sgblack@eecs.umich.eduO3ThreadContext<Impl>::setMiscReg(int misc_reg, const MiscReg &val)
3325114Sgblack@eecs.umich.edu{
3335114Sgblack@eecs.umich.edu    cpu->setMiscReg(misc_reg, val, thread->threadId());
3345114Sgblack@eecs.umich.edu
3355114Sgblack@eecs.umich.edu    conditionalSquash();
3365652Sgblack@eecs.umich.edu}
3375114Sgblack@eecs.umich.edu
3385114Sgblack@eecs.umich.edu