diff options
author | Ron Dreslinski <rdreslin@umich.edu> | 2004-11-14 16:19:11 -0500 |
---|---|---|
committer | Ron Dreslinski <rdreslin@umich.edu> | 2004-11-14 16:19:11 -0500 |
commit | f7d1166e04aa3ec2d13df382832edb5157118410 (patch) | |
tree | cf15d02622ee384e18a7327bbacd8bd0afe5afa5 | |
parent | cf5eea0e456011d2c2dba28b75497fb6980ae364 (diff) | |
parent | a89398e26271ce8e299aa77b521591c363a492ab (diff) | |
download | gem5-f7d1166e04aa3ec2d13df382832edb5157118410.tar.xz |
Merge zizzer:/z/m5/Bitkeeper/m5
into zazzer.eecs.umich.edu:/z/rdreslin/m5bk/clean
--HG--
extra : convert_revision : 170f5fd8891b02ad3cc04112c6f304ede3254dae
44 files changed, 2635 insertions, 525 deletions
diff --git a/SConscript b/SConscript index a2b1c44fa..7769d0708 100644 --- a/SConscript +++ b/SConscript @@ -271,10 +271,12 @@ full_system_sources = Split(''' dev/etherdev.cc dev/pciconfigall.cc dev/pcidev.cc + dev/pktfifo.cc dev/scsi.cc dev/scsi_ctrl.cc dev/scsi_disk.cc dev/scsi_none.cc + dev/sinic.cc dev/simple_disk.cc dev/tlaser_clock.cc dev/tlaser_ipi.cc diff --git a/arch/alpha/alpha_memory.cc b/arch/alpha/alpha_memory.cc index b9187a92e..81a1902a0 100644 --- a/arch/alpha/alpha_memory.cc +++ b/arch/alpha/alpha_memory.cc @@ -31,7 +31,6 @@ #include <vector> #include "arch/alpha/alpha_memory.hh" -#include "arch/alpha/ev5.hh" #include "base/inifile.hh" #include "base/str.hh" #include "base/trace.hh" @@ -39,6 +38,7 @@ #include "sim/builder.hh" using namespace std; +using namespace EV5; /////////////////////////////////////////////////////////////////////// // @@ -49,6 +49,8 @@ bool uncacheBit39 = false; bool uncacheBit40 = false; #endif +#define MODE2MASK(X) (1 << (X)) + AlphaTLB::AlphaTLB(const string &name, int s) : SimObject(name), size(s), nlu(0) { @@ -103,12 +105,12 @@ AlphaTLB::checkCacheability(MemReqPtr &req) #ifdef ALPHA_TLASER - if (req->paddr & PA_UNCACHED_BIT_39) { + if (req->paddr & PAddrUncachedBit39) { #else - if (req->paddr & PA_UNCACHED_BIT_43) { + if (req->paddr & PAddrUncachedBit43) { #endif // IPR memory space not implemented - if (PA_IPR_SPACE(req->paddr)) { + if (PAddrIprSpace(req->paddr)) { if (!req->xc->misspeculating()) { switch (req->paddr) { case ULL(0xFFFFF00188): @@ -126,7 +128,7 @@ AlphaTLB::checkCacheability(MemReqPtr &req) #ifndef ALPHA_TLASER // Clear bits 42:35 of the physical address (10-2 in Tsunami manual) - req->paddr &= PA_UNCACHED_MASK; + req->paddr &= PAddrUncachedMask; #endif } } @@ -135,8 +137,9 @@ AlphaTLB::checkCacheability(MemReqPtr &req) // insert a new TLB entry void -AlphaTLB::insert(Addr vaddr, AlphaISA::PTE &pte) +AlphaTLB::insert(Addr addr, AlphaISA::PTE &pte) { + AlphaISA::VAddr vaddr = addr; if (table[nlu].valid) { Addr oldvpn = table[nlu].tag; PageTable::iterator i = lookupTable.find(oldvpn); @@ -157,14 +160,13 @@ AlphaTLB::insert(Addr vaddr, AlphaISA::PTE &pte) lookupTable.erase(i); } - Addr vpn = VA_VPN(vaddr); - DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vpn, pte.ppn); + DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn); table[nlu] = pte; - table[nlu].tag = vpn; + table[nlu].tag = vaddr.vpn(); table[nlu].valid = true; - lookupTable.insert(make_pair(vpn, nlu)); + lookupTable.insert(make_pair(vaddr.vpn(), nlu)); nextnlu(); } @@ -197,21 +199,22 @@ AlphaTLB::flushProcesses() } void -AlphaTLB::flushAddr(Addr vaddr, uint8_t asn) +AlphaTLB::flushAddr(Addr addr, uint8_t asn) { - Addr vpn = VA_VPN(vaddr); + AlphaISA::VAddr vaddr = addr; - PageTable::iterator i = lookupTable.find(vpn); + PageTable::iterator i = lookupTable.find(vaddr.vpn()); if (i == lookupTable.end()) return; - while (i->first == vpn) { + while (i->first == vaddr.vpn()) { int index = i->second; AlphaISA::PTE *pte = &table[index]; assert(pte->valid); - if (vpn == pte->tag && (pte->asma || pte->asn == asn)) { - DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vpn, pte->ppn); + if (vaddr.vpn() == pte->tag && (pte->asma || pte->asn == asn)) { + DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(), + pte->ppn); // invalidate this entry pte->valid = false; @@ -287,7 +290,7 @@ AlphaITB::fault(Addr pc, ExecContext *xc) const if (!xc->misspeculating()) { ipr[AlphaISA::IPR_ITB_TAG] = pc; ipr[AlphaISA::IPR_IFAULT_VA_FORM] = - ipr[AlphaISA::IPR_IVPTBR] | (VA_VPN(pc) << 3); + ipr[AlphaISA::IPR_IVPTBR] | (AlphaISA::VAddr(pc).vpn() << 3); } } @@ -297,9 +300,9 @@ AlphaITB::translate(MemReqPtr &req) const { InternalProcReg *ipr = req->xc->regs.ipr; - if (PC_PAL(req->vaddr)) { + if (AlphaISA::PcPAL(req->vaddr)) { // strip off PAL PC marker (lsb is 1) - req->paddr = (req->vaddr & ~3) & PA_IMPL_MASK; + req->paddr = (req->vaddr & ~3) & PAddrImplMask; hits++; return No_Fault; } @@ -319,24 +322,23 @@ AlphaITB::translate(MemReqPtr &req) const // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6 #ifdef ALPHA_TLASER if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) && - VA_SPACE_EV5(req->vaddr) == 2) { + VAddrSpaceEV5(req->vaddr) == 2) { #else - if (VA_SPACE_EV6(req->vaddr) == 0x7e) { + if (VAddrSpaceEV6(req->vaddr) == 0x7e) { #endif - - // only valid in kernel mode - if (ICM_CM(ipr[AlphaISA::IPR_ICM]) != AlphaISA::mode_kernel) { + if (ICM_CM(ipr[AlphaISA::IPR_ICM]) != + AlphaISA::mode_kernel) { fault(req->vaddr, req->xc); acv++; return ITB_Acv_Fault; } - req->paddr = req->vaddr & PA_IMPL_MASK; + req->paddr = req->vaddr & PAddrImplMask; #ifndef ALPHA_TLASER // sign extend the physical address properly - if (req->paddr & PA_UNCACHED_BIT_40) + if (req->paddr & PAddrUncachedBit40) req->paddr |= ULL(0xf0000000000); else req->paddr &= ULL(0xffffffffff); @@ -344,8 +346,8 @@ AlphaITB::translate(MemReqPtr &req) const } else { // not a physical address: need to look up pte - AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr), - DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN])); + AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(), + DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN])); if (!pte) { fault(req->vaddr, req->xc); @@ -353,7 +355,8 @@ AlphaITB::translate(MemReqPtr &req) const return ITB_Fault_Fault; } - req->paddr = PA_PFN2PA(pte->ppn) + VA_POFS(req->vaddr & ~3); + req->paddr = (pte->ppn << AlphaISA::PageShift) + + (AlphaISA::VAddr(req->vaddr).offset() & ~3); // check permissions for this access if (!(pte->xre & (1 << ICM_CM(ipr[AlphaISA::IPR_ICM])))) { @@ -368,7 +371,7 @@ AlphaITB::translate(MemReqPtr &req) const } // check that the physical address is ok (catch bad physical addresses) - if (req->paddr & ~PA_IMPL_MASK) + if (req->paddr & ~PAddrImplMask) return Machine_Check_Fault; checkCacheability(req); @@ -457,7 +460,7 @@ void AlphaDTB::fault(MemReqPtr &req, uint64_t flags) const { ExecContext *xc = req->xc; - Addr vaddr = req->vaddr; + AlphaISA::VAddr vaddr = req->vaddr; uint64_t *ipr = xc->regs.ipr; // Set fault address and flags. Even though we're modeling an @@ -468,16 +471,17 @@ AlphaDTB::fault(MemReqPtr &req, uint64_t flags) const if (!xc->misspeculating() && !(req->flags & VPTE) && !(req->flags & NO_FAULT)) { // set VA register with faulting address - ipr[AlphaISA::IPR_VA] = vaddr; + ipr[AlphaISA::IPR_VA] = req->vaddr; // set MM_STAT register flags - ipr[AlphaISA::IPR_MM_STAT] = (((OPCODE(xc->getInst()) & 0x3f) << 11) - | ((RA(xc->getInst()) & 0x1f) << 6) - | (flags & 0x3f)); + ipr[AlphaISA::IPR_MM_STAT] = + (((Opcode(xc->getInst()) & 0x3f) << 11) + | ((Ra(xc->getInst()) & 0x1f) << 6) + | (flags & 0x3f)); // set VA_FORM register with faulting formatted address ipr[AlphaISA::IPR_VA_FORM] = - ipr[AlphaISA::IPR_MVPTBR] | (VA_VPN(vaddr) << 3); + ipr[AlphaISA::IPR_MVPTBR] | (vaddr.vpn() << 3); } } @@ -500,7 +504,7 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const return Alignment_Fault; } - if (PC_PAL(pc)) { + if (pc & 0x1) { mode = (req->flags & ALTMODE) ? (AlphaISA::mode_type)ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE]) : AlphaISA::mode_kernel; @@ -511,8 +515,9 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const } else { // verify that this is a good virtual address if (!validVirtualAddress(req->vaddr)) { - fault(req, (write ? MM_STAT_WR_MASK : 0) | MM_STAT_BAD_VA_MASK | - MM_STAT_ACV_MASK); + fault(req, (write ? MM_STAT_WR_MASK : 0) | + MM_STAT_BAD_VA_MASK | + MM_STAT_ACV_MASK); if (write) { write_acv++; } else { read_acv++; } return DTB_Fault_Fault; @@ -521,24 +526,25 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const // Check for "superpage" mapping #ifdef ALPHA_TLASER if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) && - VA_SPACE_EV5(req->vaddr) == 2) { + VAddrSpaceEV5(req->vaddr) == 2) { #else - if (VA_SPACE_EV6(req->vaddr) == 0x7e) { + if (VAddrSpaceEV6(req->vaddr) == 0x7e) { #endif // only valid in kernel mode if (DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]) != AlphaISA::mode_kernel) { - fault(req, ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_ACV_MASK)); + fault(req, ((write ? MM_STAT_WR_MASK : 0) | + MM_STAT_ACV_MASK)); if (write) { write_acv++; } else { read_acv++; } return DTB_Acv_Fault; } - req->paddr = req->vaddr & PA_IMPL_MASK; + req->paddr = req->vaddr & PAddrImplMask; #ifndef ALPHA_TLASER // sign extend the physical address properly - if (req->paddr & PA_UNCACHED_BIT_40) + if (req->paddr & PAddrUncachedBit40) req->paddr |= ULL(0xf0000000000); else req->paddr &= ULL(0xffffffffff); @@ -551,36 +557,39 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const read_accesses++; // not a physical address: need to look up pte - AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr), - DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN])); + AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(), + DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN])); if (!pte) { // page fault - fault(req, - (write ? MM_STAT_WR_MASK : 0) | MM_STAT_DTB_MISS_MASK); + fault(req, (write ? MM_STAT_WR_MASK : 0) | + MM_STAT_DTB_MISS_MASK); if (write) { write_misses++; } else { read_misses++; } return (req->flags & VPTE) ? Pdtb_Miss_Fault : Ndtb_Miss_Fault; } - req->paddr = PA_PFN2PA(pte->ppn) | VA_POFS(req->vaddr); + req->paddr = (pte->ppn << AlphaISA::PageShift) + + AlphaISA::VAddr(req->vaddr).offset(); if (write) { if (!(pte->xwe & MODE2MASK(mode))) { // declare the instruction access fault - fault(req, (MM_STAT_WR_MASK | MM_STAT_ACV_MASK | - (pte->fonw ? MM_STAT_FONW_MASK : 0))); + fault(req, MM_STAT_WR_MASK | + MM_STAT_ACV_MASK | + (pte->fonw ? MM_STAT_FONW_MASK : 0)); write_acv++; return DTB_Fault_Fault; } if (pte->fonw) { - fault(req, MM_STAT_WR_MASK | MM_STAT_FONW_MASK); + fault(req, MM_STAT_WR_MASK | + MM_STAT_FONW_MASK); write_acv++; return DTB_Fault_Fault; } } else { if (!(pte->xre & MODE2MASK(mode))) { - fault(req, (MM_STAT_ACV_MASK | - (pte->fonr ? MM_STAT_FONR_MASK : 0))); + fault(req, MM_STAT_ACV_MASK | + (pte->fonr ? MM_STAT_FONR_MASK : 0)); read_acv++; return DTB_Acv_Fault; } @@ -599,7 +608,7 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const } // check that the physical address is ok (catch bad physical addresses) - if (req->paddr & ~PA_IMPL_MASK) + if (req->paddr & ~PAddrImplMask) return Machine_Check_Fault; checkCacheability(req); diff --git a/arch/alpha/alpha_memory.hh b/arch/alpha/alpha_memory.hh index 42bc03ddd..0d4b8d1f2 100644 --- a/arch/alpha/alpha_memory.hh +++ b/arch/alpha/alpha_memory.hh @@ -31,9 +31,10 @@ #include <map> +#include "arch/alpha/isa_traits.hh" +#include "base/statistics.hh" #include "mem/mem_req.hh" #include "sim/sim_object.hh" -#include "base/statistics.hh" class ExecContext; @@ -66,8 +67,8 @@ class AlphaTLB : public SimObject // static helper functions... really EV5 VM traits static bool validVirtualAddress(Addr vaddr) { // unimplemented bits must be all 0 or all 1 - Addr unimplBits = vaddr & VA_UNIMPL_MASK; - return (unimplBits == 0) || (unimplBits == VA_UNIMPL_MASK); + Addr unimplBits = vaddr & EV5::VAddrUnImplMask; + return (unimplBits == 0) || (unimplBits == EV5::VAddrUnImplMask); } static void checkCacheability(MemReqPtr &req); diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc index 34b65a915..2e32da531 100644 --- a/arch/alpha/ev5.cc +++ b/arch/alpha/ev5.cc @@ -15,9 +15,7 @@ #ifdef FULL_SYSTEM -#ifndef SYSTEM_EV5 -#error This code is only valid for EV5 systems -#endif +using namespace EV5; //////////////////////////////////////////////////////////////////////// // @@ -96,7 +94,7 @@ AlphaISA::initIPRs(RegFile *regs) uint64_t *ipr = regs->ipr; bzero((char *)ipr, NumInternalProcRegs * sizeof(InternalProcReg)); - ipr[IPR_PAL_BASE] = PAL_BASE; + ipr[IPR_PAL_BASE] = PalBase; ipr[IPR_MCSR] = 0x6; } diff --git a/arch/alpha/ev5.hh b/arch/alpha/ev5.hh index 7b1ff4a2f..317f3d19d 100644 --- a/arch/alpha/ev5.hh +++ b/arch/alpha/ev5.hh @@ -1,116 +1,79 @@ /* $Id$ */ -#ifndef __EV5_H__ -#define __EV5_H__ +#ifndef __ARCH_ALPHA_EV5_HH__ +#define __ARCH_ALPHA_EV5_HH__ -#ifndef SYSTEM_EV5 -#error This code is only valid for EV5 systems -#endif - -#define MODE2MASK(X) (1 << (X)) - -// Alpha IPR register accessors -#define PC_PAL(X) ((X) & 0x1) -#define MCSR_SP(X) (((X) >> 1) & 0x3) - -#define ICSR_SDE(X) (((X) >> 30) & 0x1) -#define ICSR_SPE(X) (((X) >> 28) & 0x3) -#define ICSR_FPE(X) (((X) >> 26) & 0x1) - -#define ALT_MODE_AM(X) (((X) >> 3) & 0x3) - -#define DTB_CM_CM(X) (((X) >> 3) & 0x3) - -#ifdef ALPHA_TLASER -#define DTB_ASN_ASN(X) (((X) >> 57) & 0x7f) -#define DTB_PTE_PPN(X) (((X) >> 32) & 0x07ffffff) -#else -#define DTB_ASN_ASN(X) (((X) >> 57) & 0xff) -#define DTB_PTE_PPN(X) (((X) >> 32) & 0x07fffffff) -#endif - -#define DTB_PTE_XRE(X) (((X) >> 8) & 0xf) -#define DTB_PTE_XWE(X) (((X) >> 12) & 0xf) -#define DTB_PTE_FONR(X) (((X) >> 1) & 0x1) -#define DTB_PTE_FONW(X) (((X) >> 2) & 0x1) -#define DTB_PTE_GH(X) (((X) >> 5) & 0x3) -#define DTB_PTE_ASMA(X) (((X) >> 4) & 0x1) - -#define ICM_CM(X) (((X) >> 3) & 0x3) +namespace EV5 { #ifdef ALPHA_TLASER -#define ITB_ASN_ASN(X) (((X) >> 4) & 0x7f) -#define ITB_PTE_PPN(X) (((X) >> 32) & 0x07ffffff) +const uint64_t AsnMask = ULL(0x7f); #else -#define ITB_ASN_ASN(X) (((X) >> 4) & 0xff) -#define ITB_PTE_PPN(X) (((X) >> 32) & 0x07fffffff) +const uint64_t AsnMask = ULL(0xff); #endif -#define ITB_PTE_XRE(X) (((X) >> 8) & 0xf) -#define ITB_PTE_FONR(X) (((X) >> 1) & 0x1) -#define ITB_PTE_FONW(X) (((X) >> 2) & 0x1) -#define ITB_PTE_GH(X) (((X) >> 5) & 0x3) -#define ITB_PTE_ASMA(X) (((X) >> 4) & 0x1) - -#define VA_UNIMPL_MASK ULL(0xfffff80000000000) -#define VA_IMPL_MASK ULL(0x000007ffffffffff) -#define VA_IMPL(X) ((X) & VA_IMPL_MASK) -#define VA_VPN(X) (VA_IMPL(X) >> 13) -#define VA_SPACE_EV5(X) (((X) >> 41) & 0x3) -#define VA_SPACE_EV6(X) (((X) >> 41) & 0x7f) -#define VA_POFS(X) ((X) & 0x1fff) +const int VAddrImplBits = 43; +const Addr VAddrImplMask = (ULL(1) << VAddrImplBits) - 1; +const Addr VAddrUnImplMask = ~VAddrImplMask; +inline Addr VAddrImpl(Addr a) { return a & VAddrImplMask; } +inline Addr VAddrVPN(Addr a) { return a >> AlphaISA::PageShift; } +inline Addr VAddrOffset(Addr a) { return a & AlphaISA::PageOffset; } +inline Addr VAddrSpaceEV5(Addr a) { return a >> 41 & 0x3; } +inline Addr VAddrSpaceEV6(Addr a) { return a >> 41 & 0x7f; } -#define PA_UNCACHED_BIT_39 ULL(0x8000000000) -#define PA_UNCACHED_BIT_40 ULL(0x10000000000) -#define PA_UNCACHED_BIT_43 ULL(0x80000000000) -#define PA_UNCACHED_MASK ULL(0x807ffffffff) // Clear PA<42:35> #ifdef ALPHA_TLASER -#define PA_IPR_SPACE(X) ((X) >= ULL(0xFFFFF00000)) -#define PA_IMPL_MASK ULL(0xffffffffff) +inline bool PAddrIprSpace(Addr a) { return a >= ULL(0xFFFFF00000); } +const int PAddrImplBits = 40; #else -#define PA_IPR_SPACE(X) ((X) >= ULL(0xFFFFFF00000)) -#define PA_IMPL_MASK ULL(0xfffffffffff) // for Tsunami +inline bool PAddrIprSpace(Addr a) { return a >= ULL(0xFFFFFF00000); } +const int PAddrImplBits = 44; // for Tsunami #endif - -#define PA_PFN2PA(X) ((X) << 13) - - -#define MM_STAT_BAD_VA_MASK 0x0020 -#define MM_STAT_DTB_MISS_MASK 0x0010 -#define MM_STAT_FONW_MASK 0x0008 -#define MM_STAT_FONR_MASK 0x0004 -#define MM_STAT_ACV_MASK 0x0002 -#define MM_STAT_WR_MASK 0x0001 - -#define OPCODE(X) (X >> 26) & 0x3f -#define RA(X) (X >> 21) & 0x1f - -//////////////////////////////////////////////////////////////////////// -// -// -// - -// VPTE size for HW_LD/HW_ST -#define HW_VPTE ((inst >> 11) & 0x1) - -// QWORD size for HW_LD/HW_ST -#define HW_QWORD ((inst >> 12) & 0x1) - -// ALT mode for HW_LD/HW_ST -#define HW_ALT (((inst >> 14) & 0x1) ? ALTMODE : 0) - -// LOCK/COND mode for HW_LD/HW_ST -#define HW_LOCK (((inst >> 10) & 0x1) ? LOCKED : 0) -#define HW_COND (((inst >> 10) & 0x1) ? LOCKED : 0) - -// PHY size for HW_LD/HW_ST -#define HW_PHY (((inst >> 15) & 0x1) ? PHYSICAL : 0) - -// OFFSET for HW_LD/HW_ST -#define HW_OFS (inst & 0x3ff) - - -#define PAL_BASE 0x4000 -#define PAL_MAX 0x10000 - -#endif //__EV5_H__ +const Addr PAddrImplMask = (ULL(1) << PAddrImplBits) - 1; +const Addr PAddrUncachedBit39 = ULL(0x8000000000); +const Addr PAddrUncachedBit40 = ULL(0x10000000000); +const Addr PAddrUncachedBit43 = ULL(0x80000000000); +const Addr PAddrUncachedMask = ULL(0x807ffffffff); // Clear PA<42:35> + +inline int DTB_ASN_ASN(uint64_t reg) { return reg >> 57 & AsnMask; } +inline Addr DTB_PTE_PPN(uint64_t reg) +{ return reg >> 32 & (ULL(1) << PAddrImplBits - AlphaISA::PageShift) - 1; } +inline int DTB_PTE_XRE(uint64_t reg) { return reg >> 8 & 0xf; } +inline int DTB_PTE_XWE(uint64_t reg) { return reg >> 12 & 0xf; } +inline int DTB_PTE_FONR(uint64_t reg) { return reg >> 1 & 0x1; } +inline int DTB_PTE_FONW(uint64_t reg) { return reg >> 2 & 0x1; } +inline int DTB_PTE_GH(uint64_t reg) { return reg >> 5 & 0x3; } +inline int DTB_PTE_ASMA(uint64_t reg) { return reg >> 4 & 0x1; } + +inline int ITB_ASN_ASN(uint64_t reg) { return reg >> 4 & AsnMask; } +inline Addr ITB_PTE_PPN(uint64_t reg) +{ return reg >> 32 & (ULL(1) << PAddrImplBits - AlphaISA::PageShift) - 1; } +inline int ITB_PTE_XRE(uint64_t reg) { return reg >> 8 & 0xf; } +inline bool ITB_PTE_FONR(uint64_t reg) { return reg >> 1 & 0x1; } +inline bool ITB_PTE_FONW(uint64_t reg) { return reg >> 2 & 0x1; } +inline int ITB_PTE_GH(uint64_t reg) { return reg >> 5 & 0x3; } +inline bool ITB_PTE_ASMA(uint64_t reg) { return reg >> 4 & 0x1; } + +inline uint64_t MCSR_SP(uint64_t reg) { return reg >> 1 & 0x3; } + +inline bool ICSR_SDE(uint64_t reg) { return reg >> 30 & 0x1; } +inline int ICSR_SPE(uint64_t reg) { return reg >> 28 & 0x3; } +inline bool ICSR_FPE(uint64_t reg) { return reg >> 26 & 0x1; } + +inline uint64_t ALT_MODE_AM(uint64_t reg) { return reg >> 3 & 0x3; } +inline uint64_t DTB_CM_CM(uint64_t reg) { return reg >> 3 & 0x3; } +inline uint64_t ICM_CM(uint64_t reg) { return reg >> 3 & 0x3; } + +const uint64_t MM_STAT_BAD_VA_MASK = ULL(0x0020); +const uint64_t MM_STAT_DTB_MISS_MASK = ULL(0x0010); +const uint64_t MM_STAT_FONW_MASK = ULL(0x0008); +const uint64_t MM_STAT_FONR_MASK = ULL(0x0004); +const uint64_t MM_STAT_ACV_MASK = ULL(0x0002); +const uint64_t MM_STAT_WR_MASK = ULL(0x0001); +inline int Opcode(AlphaISA::MachInst inst) { return inst >> 26 & 0x3f; } +inline int Ra(AlphaISA::MachInst inst) { return inst >> 21 & 0x1f; } + +const Addr PalBase = 0x4000; +const Addr PalMax = 0x10000; + +/* namespace EV5 */ } + +#endif // __ARCH_ALPHA_EV5_HH__ diff --git a/arch/alpha/isa_desc b/arch/alpha/isa_desc index 9d65a02f0..5154d78d1 100644 --- a/arch/alpha/isa_desc +++ b/arch/alpha/isa_desc @@ -38,14 +38,12 @@ output exec {{ #include <fenv.h> #endif -#include "cpu/base_cpu.hh" -#include "cpu/exetrace.hh" -#include "sim/sim_exit.hh" - #ifdef FULL_SYSTEM -#include "arch/alpha/ev5.hh" #include "arch/alpha/pseudo_inst.hh" #endif +#include "cpu/base_cpu.hh" +#include "cpu/exetrace.hh" +#include "sim/sim_exit.hh" }}; //////////////////////////////////////////////////////////////////// @@ -515,7 +513,7 @@ output exec {{ inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) { Fault fault = No_Fault; // dummy... this ipr access should not fault - if (!ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) { + if (!EV5::ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) { fault = Fen_Fault; } return fault; diff --git a/arch/alpha/isa_traits.hh b/arch/alpha/isa_traits.hh index b22b2fa29..ff3da1502 100644 --- a/arch/alpha/isa_traits.hh +++ b/arch/alpha/isa_traits.hh @@ -26,8 +26,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __ISA_TRAITS_HH__ -#define __ISA_TRAITS_HH__ +#ifndef __ARCH_ALPHA_ISA_TRAITS_HH__ +#define __ARCH_ALPHA_ISA_TRAITS_HH__ #include "arch/alpha/faults.hh" #include "base/misc.hh" @@ -42,6 +42,11 @@ class Checkpoint; template <class ISA> class StaticInst; template <class ISA> class StaticInstPtr; +namespace EV5 { +int DTB_ASN_ASN(uint64_t reg); +int ITB_ASN_ASN(uint64_t reg); +} + class AlphaISA { public: @@ -160,6 +165,8 @@ static const Addr PageOffset = PageBytes - 1; InternalProcReg ipr[NumInternalProcRegs]; // internal processor regs int intrflag; // interrupt flag bool pal_shadow; // using pal_shadow registers + inline int instAsid() { return EV5::ITB_ASN_ASN(ipr[IPR_ITB_ASN]); } + inline int dataAsid() { return EV5::DTB_ASN_ASN(ipr[IPR_DTB_ASN]); } #endif // FULL_SYSTEM void serialize(std::ostream &os); @@ -281,9 +288,7 @@ typedef TheISA::InternalProcReg InternalProcReg; const int NumInternalProcRegs = TheISA::NumInternalProcRegs; const int NumInterruptLevels = TheISA::NumInterruptLevels; -// more stuff that should be imported here, but I'm too tired to do it -// right now... #include "arch/alpha/ev5.hh" #endif -#endif // __ALPHA_ISA_H__ +#endif // __ARCH_ALPHA_ISA_TRAITS_HH__ diff --git a/arch/alpha/vtophys.cc b/arch/alpha/vtophys.cc index a8af8f238..e26721aab 100644 --- a/arch/alpha/vtophys.cc +++ b/arch/alpha/vtophys.cc @@ -85,7 +85,7 @@ vtophys(ExecContext *xc, Addr addr) Addr paddr = 0; //@todo Andrew couldn't remember why he commented some of this code //so I put it back in. Perhaps something to do with gdb debugging? - if (PC_PAL(vaddr) && (vaddr < PAL_MAX)) { + if (AlphaISA::PcPAL(vaddr) && (vaddr < EV5::PalMax)) { paddr = vaddr & ~ULL(1); } else { if (AlphaISA::IsK0Seg(vaddr)) { diff --git a/base/remote_gdb.cc b/base/remote_gdb.cc index 598f03c35..484a01944 100644 --- a/base/remote_gdb.cc +++ b/base/remote_gdb.cc @@ -350,7 +350,7 @@ RemoteGDB::acc(Addr va, size_t len) * but there is no easy way to do it. */ - if (PC_PAL(va) || va < 0x10000) + if (AlphaISA::PcPAL(va) || va < 0x10000) return true; Addr ptbr = context->regs.ipr[AlphaISA::IPR_PALtemp20]; diff --git a/build/SConstruct b/build/SConstruct index 6b71fa585..3d7db1db2 100644 --- a/build/SConstruct +++ b/build/SConstruct @@ -93,7 +93,7 @@ def AlphaConfig(env): def KernelConfig(env): env.Replace(TARGET_ISA = 'alpha') env.Replace(FULL_SYSTEM = True) - env.Append(CPPDEFINES = ['FULL_SYSTEM', 'SYSTEM_EV5']) + env.Append(CPPDEFINES = ['FULL_SYSTEM']) # Base configurations map. configs_map = { diff --git a/configs/boot/nfs-client.rcS b/configs/boot/nfs-client.rcS index a8c45f4a5..b0763b77f 100755 --- a/configs/boot/nfs-client.rcS +++ b/configs/boot/nfs-client.rcS @@ -45,7 +45,6 @@ mkdir /nfs mount 10.0.0.1:/nfs /nfs echo "done." -/bin/bonnie++ -u 99 -s 120 -r 0 +/bin/bonnie++ -u 99 -s 100 -r 0 -n 0 -d /nfs -echo -n "starting bash shell..." -/bin/bash +/sbin/m5 exit diff --git a/configs/boot/nfs-server.rcS b/configs/boot/nfs-server.rcS index c5b17348e..feefc057f 100755 --- a/configs/boot/nfs-server.rcS +++ b/configs/boot/nfs-server.rcS @@ -47,14 +47,13 @@ echo "/nfs 10.0.0.0/255.0.0.0(rw,sync,no_root_squash)" > /etc/exports /sbin/insmod /modules/scsi_debug.ko dev_size_mb=128 echo -n "creating partition and formatting..." -echo "1,126,L" > /tmp/sfdisk.run -echo ";" >> /tmp/sfdisk.run -echo ";" >> /tmp/sfdisk.run -/usr/sbin/sfdisk --force /dev/sda < /tmp/sfdisk.run +echo "1,120,L" > /tmp/sfdisk.run +/usr/sbin/sfdisk -uM --force /dev/sda < /tmp/sfdisk.run /sbin/mke2fs /dev/sda1 mkdir /nfs /bin/mount /dev/sda1 /nfs chmod a+rwx /nfs +/usr/sbin/sfdisk -uM -l /dev/sda echo "done." echo -n "starting nfs kernel server..." diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh index 2ba2d7524..8437a5585 100644 --- a/cpu/exec_context.hh +++ b/cpu/exec_context.hh @@ -196,8 +196,8 @@ class ExecContext #ifdef FULL_SYSTEM bool validInstAddr(Addr addr) { return true; } bool validDataAddr(Addr addr) { return true; } - int getInstAsid() { return ITB_ASN_ASN(regs.ipr[TheISA::IPR_ITB_ASN]); } - int getDataAsid() { return DTB_ASN_ASN(regs.ipr[TheISA::IPR_DTB_ASN]); } + int getInstAsid() { return regs.instAsid(); } + int getDataAsid() { return regs.dataAsid(); } Fault translateInstReq(MemReqPtr &req) { @@ -410,7 +410,7 @@ class ExecContext int readIntrFlag() { return regs.intrflag; } void setIntrFlag(int val) { regs.intrflag = val; } Fault hwrei(); - bool inPalMode() { return PC_PAL(regs.pc); } + bool inPalMode() { return AlphaISA::PcPAL(regs.pc); } void ev5_trap(Fault fault); bool simPalCheck(int palFunc); #endif diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc index 964ab442c..7deabe2fc 100644 --- a/dev/alpha_console.cc +++ b/dev/alpha_console.cc @@ -98,7 +98,7 @@ AlphaConsole::read(MemReqPtr &req, uint8_t *data) { memset(data, 0, req->size); - Addr daddr = req->paddr - (addr & PA_IMPL_MASK); + Addr daddr = req->paddr - (addr & EV5::PAddrImplMask); switch (req->size) { @@ -198,7 +198,7 @@ AlphaConsole::write(MemReqPtr &req, const uint8_t *data) return Machine_Check_Fault; } - Addr daddr = req->paddr - (addr & PA_IMPL_MASK); + Addr daddr = req->paddr - (addr & EV5::PAddrImplMask); ExecContext *other_xc; switch (daddr) { diff --git a/dev/etherint.hh b/dev/etherint.hh index ddfe16d88..bcdf0ae06 100644 --- a/dev/etherint.hh +++ b/dev/etherint.hh @@ -31,8 +31,8 @@ * components. */ -#ifndef __ETHERINT_HH__ -#define __ETHERINT_HH__ +#ifndef __DEV_ETHERINT_HH__ +#define __DEV_ETHERINT_HH__ #include <string> @@ -54,13 +54,13 @@ class EtherInt : public SimObject virtual ~EtherInt() {} void setPeer(EtherInt *p); - virtual bool recvPacket(PacketPtr &packet) = 0; + void recvDone() { peer->sendDone(); } - bool sendPacket(PacketPtr &packet) - { - return peer ? peer->recvPacket(packet) : true; - } virtual void sendDone() = 0; + + bool sendPacket(PacketPtr packet) + { return peer ? peer->recvPacket(packet) : true; } + virtual bool recvPacket(PacketPtr packet) = 0; }; -#endif // __ETHERINT_HH__ +#endif // __DEV_ETHERINT_HH__ diff --git a/dev/etherlink.cc b/dev/etherlink.cc index ccb18d363..1e2be41fe 100644 --- a/dev/etherlink.cc +++ b/dev/etherlink.cc @@ -105,7 +105,7 @@ EtherLink::unserialize(Checkpoint *cp, const string §ion) } void -EtherLink::Link::txComplete(PacketPtr &packet) +EtherLink::Link::txComplete(PacketPtr packet) { DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); DDUMP(EthernetData, packet->data, packet->length); @@ -122,7 +122,7 @@ class LinkDelayEvent : public Event LinkDelayEvent(EtherLink::Link *link); public: - LinkDelayEvent(EtherLink::Link *link, PacketPtr &pkt, Tick when); + LinkDelayEvent(EtherLink::Link *link, PacketPtr pkt, Tick when); void process(); @@ -153,7 +153,7 @@ EtherLink::Link::txDone() } bool -EtherLink::Link::transmit(PacketPtr &pkt) +EtherLink::Link::transmit(PacketPtr pkt) { if (busy()) { DPRINTF(Ethernet, "packet not sent, link busy\n"); @@ -185,10 +185,8 @@ EtherLink::Link::serialize(ostream &os) SERIALIZE_SCALAR(event_time); } - if (packet_exists) { - nameOut(os, csprintf("%s.packet", name())); - packet->serialize(os); - } + if (packet_exists) + packet->serialize("packet", os); } void @@ -198,7 +196,7 @@ EtherLink::Link::unserialize(Checkpoint *cp, const string §ion) UNSERIALIZE_SCALAR(packet_exists); if (packet_exists) { packet = new PacketData; - packet->unserialize(cp, csprintf("%s.packet", section)); + packet->unserialize("packet", cp, section); } bool event_scheduled; @@ -217,7 +215,7 @@ LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l) setFlags(AutoDelete); } -LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr &p, Tick when) +LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr p, Tick when) : Event(&mainEventQueue), link(l), packet(p) { setFlags(AutoSerialize); @@ -238,8 +236,7 @@ LinkDelayEvent::serialize(ostream &os) Event::serialize(os); SERIALIZE_OBJPTR(link); - nameOut(os, csprintf("%s.packet", name())); - packet->serialize(os); + packet->serialize("packet", os); } @@ -248,7 +245,7 @@ LinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) { Event::unserialize(cp, section); packet = new PacketData; - packet->unserialize(cp, csprintf("%s.packet", section)); + packet->unserialize("packet", cp, section); } diff --git a/dev/etherlink.hh b/dev/etherlink.hh index 204348c6d..e998a006f 100644 --- a/dev/etherlink.hh +++ b/dev/etherlink.hh @@ -75,7 +75,7 @@ class EtherLink : public SimObject DoneEvent doneEvent; friend class LinkDelayEvent; - void txComplete(PacketPtr &packet); + void txComplete(PacketPtr packet); public: Link(const std::string &name, double rate, Tick delay, @@ -85,7 +85,7 @@ class EtherLink : public SimObject virtual const std::string name() const { return objName; } bool busy() const { return (bool)packet; } - bool transmit(PacketPtr &packet); + bool transmit(PacketPtr packet); void setTxInt(Interface *i) { assert(!txint); txint = i; } void setRxInt(Interface *i) { assert(!rxint); rxint = i; } @@ -104,7 +104,7 @@ class EtherLink : public SimObject public: Interface(const std::string &name, Link *txlink, Link *rxlink); - bool recvPacket(PacketPtr &packet) { return txlink->transmit(packet); } + bool recvPacket(PacketPtr packet) { return txlink->transmit(packet); } void sendDone() { peer->sendDone(); } }; diff --git a/dev/etherpkt.cc b/dev/etherpkt.cc index 273b8ee64..bf60bc150 100644 --- a/dev/etherpkt.cc +++ b/dev/etherpkt.cc @@ -28,22 +28,23 @@ #include <iostream> +#include "base/misc.hh" #include "dev/etherpkt.hh" #include "sim/serialize.hh" using namespace std; void -PacketData::serialize(ostream &os) +PacketData::serialize(const string &base, ostream &os) { - SERIALIZE_SCALAR(length); - SERIALIZE_ARRAY(data, length); + paramOut(os, base + ".length", length); + arrayParamOut(os, base + ".data", data, length); } void -PacketData::unserialize(Checkpoint *cp, const string §ion) +PacketData::unserialize(const string &base, Checkpoint *cp, + const string §ion) { - UNSERIALIZE_SCALAR(length); - data = new uint8_t[length]; - UNSERIALIZE_ARRAY(data, length); + paramIn(cp, section, base + ".length", length); + arrayParamIn(cp, section, base + ".data", data, length); } diff --git a/dev/etherpkt.hh b/dev/etherpkt.hh index 1b6e9858f..7a7809f0a 100644 --- a/dev/etherpkt.hh +++ b/dev/etherpkt.hh @@ -52,13 +52,15 @@ class PacketData : public RefCounted public: PacketData() : data(NULL), length(0) { } + explicit PacketData(size_t size) : data(new uint8_t[size]), length(0) { } PacketData(std::auto_ptr<uint8_t> d, int l) : data(d.release()), length(l) { } ~PacketData() { if (data) delete [] data; } public: - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(const std::string &base, std::ostream &os); + void unserialize(const std::string &base, Checkpoint *cp, + const std::string §ion); }; typedef RefCountingPtr<PacketData> PacketPtr; diff --git a/dev/ethertap.cc b/dev/ethertap.cc index b40a93c1b..03f2724b1 100644 --- a/dev/ethertap.cc +++ b/dev/ethertap.cc @@ -169,7 +169,7 @@ EtherTap::detach() } bool -EtherTap::recvPacket(PacketPtr &packet) +EtherTap::recvPacket(PacketPtr packet) { if (dump) dump->dump(packet); diff --git a/dev/ethertap.hh b/dev/ethertap.hh index 9c77a4a4f..5f760ed34 100644 --- a/dev/ethertap.hh +++ b/dev/ethertap.hh @@ -94,7 +94,7 @@ class EtherTap : public EtherInt EtherTap(const std::string &name, EtherDump *dump, int port, int bufsz); virtual ~EtherTap(); - virtual bool recvPacket(PacketPtr &packet); + virtual bool recvPacket(PacketPtr packet); virtual void sendDone(); virtual void serialize(std::ostream &os); diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc index d08e61fbf..109908ead 100644 --- a/dev/ide_ctrl.cc +++ b/dev/ide_ctrl.cc @@ -34,16 +34,15 @@ #include "base/trace.hh" #include "cpu/intr_control.hh" #include "dev/dma.hh" -#include "dev/pcireg.h" -#include "dev/pciconfigall.hh" -#include "dev/ide_disk.hh" #include "dev/ide_ctrl.hh" -#include "dev/tsunami_cchip.hh" +#include "dev/ide_disk.hh" +#include "dev/pciconfigall.hh" +#include "dev/pcireg.h" +#include "dev/platform.hh" #include "mem/bus/bus.hh" +#include "mem/bus/dma_interface.hh" #include "mem/bus/pio_interface.hh" #include "mem/bus/pio_interface_impl.hh" -#include "mem/bus/dma_interface.hh" -#include "dev/tsunami.hh" #include "mem/functional_mem/memory_control.hh" #include "mem/functional_mem/physical_memory.hh" #include "sim/builder.hh" @@ -55,13 +54,8 @@ using namespace std; // Initialization and destruction //// -IdeController::IdeController(const string &name, IntrControl *ic, - const vector<IdeDisk *> &new_disks, - MemoryController *mmu, PciConfigAll *cf, - PciConfigData *cd, Tsunami *t, uint32_t bus_num, - uint32_t dev_num, uint32_t func_num, - Bus *host_bus, Tick pio_latency, HierParams *hier) - : PciDev(name, mmu, cf, cd, bus_num, dev_num, func_num), tsunami(t) +IdeController::IdeController(Params *p) + : PciDev(p) { // initialize the PIO interface addresses pri_cmd_addr = 0; @@ -96,23 +90,25 @@ IdeController::IdeController(const string &name, IntrControl *ic, memset(cmd_in_progress, 0, sizeof(cmd_in_progress)); // create the PIO and DMA interfaces - if (host_bus) { - pioInterface = newPioInterface(name, hier, host_bus, this, + if (params()->host_bus) { + pioInterface = newPioInterface(name(), params()->hier, + params()->host_bus, this, &IdeController::cacheAccess); - dmaInterface = new DMAInterface<Bus>(name + ".dma", host_bus, - host_bus, 1); - pioLatency = pio_latency * host_bus->clockRatio; + dmaInterface = new DMAInterface<Bus>(name() + ".dma", + params()->host_bus, + params()->host_bus, 1); + pioLatency = params()->pio_latency * params()->host_bus->clockRatio; } // setup the disks attached to controller memset(disks, 0, sizeof(IdeDisk *) * 4); - if (new_disks.size() > 3) + if (params()->disks.size() > 3) panic("IDE controllers support a maximum of 4 devices attached!\n"); - for (int i = 0; i < new_disks.size(); i++) { - disks[i] = new_disks[i]; + for (int i = 0; i < params()->disks.size(); i++) { + disks[i] = params()->disks[i]; disks[i]->setController(this, dmaInterface); } } @@ -236,22 +232,6 @@ IdeController::setDmaComplete(IdeDisk *disk) } //// -// Interrupt handling -//// - -void -IdeController::intrPost() -{ - tsunami->postPciInt(configData->config.hdr.pci0.interruptLine); -} - -void -IdeController::intrClear() -{ - tsunami->clearPciInt(configData->config.hdr.pci0.interruptLine); -} - -//// // Bus timing and bus access functions //// @@ -377,7 +357,7 @@ IdeController::WriteConfig(int offset, int size, uint32_t data) pioInterface->addAddrRange(RangeSize(pri_cmd_addr, pri_cmd_size)); - pri_cmd_addr &= PA_UNCACHED_MASK; + pri_cmd_addr &= EV5::PAddrUncachedMask; } break; @@ -388,7 +368,7 @@ IdeController::WriteConfig(int offset, int size, uint32_t data) pioInterface->addAddrRange(RangeSize(pri_ctrl_addr, pri_ctrl_size)); - pri_ctrl_addr &= PA_UNCACHED_MASK; + pri_ctrl_addr &= EV5::PAddrUncachedMask; } break; @@ -399,7 +379,7 @@ IdeController::WriteConfig(int offset, int size, uint32_t data) pioInterface->addAddrRange(RangeSize(sec_cmd_addr, sec_cmd_size)); - sec_cmd_addr &= PA_UNCACHED_MASK; + sec_cmd_addr &= EV5::PAddrUncachedMask; } break; @@ -410,7 +390,7 @@ IdeController::WriteConfig(int offset, int size, uint32_t data) pioInterface->addAddrRange(RangeSize(sec_ctrl_addr, sec_ctrl_size)); - sec_ctrl_addr &= PA_UNCACHED_MASK; + sec_ctrl_addr &= EV5::PAddrUncachedMask; } break; @@ -420,7 +400,7 @@ IdeController::WriteConfig(int offset, int size, uint32_t data) if (pioInterface) pioInterface->addAddrRange(RangeSize(bmi_addr, bmi_size)); - bmi_addr &= PA_UNCACHED_MASK; + bmi_addr &= EV5::PAddrUncachedMask; } break; } @@ -684,12 +664,11 @@ IdeController::unserialize(Checkpoint *cp, const std::string §ion) BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController) - SimObjectParam<IntrControl *> intr_ctrl; SimObjectVectorParam<IdeDisk *> disks; SimObjectParam<MemoryController *> mmu; SimObjectParam<PciConfigAll *> configspace; SimObjectParam<PciConfigData *> configdata; - SimObjectParam<Tsunami *> tsunami; + SimObjectParam<Platform *> platform; Param<uint32_t> pci_bus; Param<uint32_t> pci_dev; Param<uint32_t> pci_func; @@ -701,12 +680,11 @@ END_DECLARE_SIM_OBJECT_PARAMS(IdeController) BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController) - INIT_PARAM(intr_ctrl, "Interrupt Controller"), INIT_PARAM(disks, "IDE disks attached to this controller"), INIT_PARAM(mmu, "Memory controller"), INIT_PARAM(configspace, "PCI Configspace"), INIT_PARAM(configdata, "PCI Config data"), - INIT_PARAM(tsunami, "Tsunami chipset pointer"), + INIT_PARAM(platform, "Platform pointer"), INIT_PARAM(pci_bus, "PCI bus ID"), INIT_PARAM(pci_dev, "PCI device number"), INIT_PARAM(pci_func, "PCI function code"), @@ -718,9 +696,21 @@ END_INIT_SIM_OBJECT_PARAMS(IdeController) CREATE_SIM_OBJECT(IdeController) { - return new IdeController(getInstanceName(), intr_ctrl, disks, mmu, - configspace, configdata, tsunami, pci_bus, - pci_dev, pci_func, io_bus, pio_latency, hier); + IdeController::Params *params = new IdeController::Params; + params->name = getInstanceName(); + params->mmu = mmu; + params->configSpace = configspace; + params->configData = configdata; + params->plat = platform; + params->busNum = pci_bus; + params->deviceNum = pci_dev; + params->functionNum = pci_func; + + params->disks = disks; + params->host_bus = io_bus; + params->pio_latency = pio_latency; + params->hier = hier; + return new IdeController(params); } REGISTER_SIM_OBJECT("IdeController", IdeController) diff --git a/dev/ide_ctrl.hh b/dev/ide_ctrl.hh index b29e5ae9a..f1082d094 100644 --- a/dev/ide_ctrl.hh +++ b/dev/ide_ctrl.hh @@ -80,14 +80,14 @@ typedef enum RegType { BMI_BLOCK } RegType_t; +class BaseInterface; +class Bus; +class HierParams; class IdeDisk; class IntrControl; class PciConfigAll; -class Tsunami; class PhysicalMemory; -class BaseInterface; -class HierParams; -class Bus; +class Platform; /** * Device model for an Intel PIIX4 IDE controller @@ -95,6 +95,8 @@ class Bus; class IdeController : public PciDev { + friend class IdeDisk; + private: /** Primary command block registers */ Addr pri_cmd_addr; @@ -125,10 +127,6 @@ class IdeController : public PciDev bool bm_enabled; bool cmd_in_progress[4]; - public: - /** Pointer to the chipset */ - Tsunami *tsunami; - private: /** IDE disks connected to controller */ IdeDisk *disks[4]; @@ -149,37 +147,23 @@ class IdeController : public PciDev bool isDiskSelected(IdeDisk *diskPtr); public: - /** - * Constructs and initializes this controller. - * @param name The name of this controller. - * @param ic The interrupt controller. - * @param mmu The memory controller - * @param cf PCI config space - * @param cd PCI config data - * @param bus_num The PCI bus number - * @param dev_num The PCI device number - * @param func_num The PCI function number - * @param host_bus The host bus to connect to - * @param hier The hierarchy parameters - */ - IdeController(const std::string &name, IntrControl *ic, - const std::vector<IdeDisk *> &new_disks, - MemoryController *mmu, PciConfigAll *cf, - PciConfigData *cd, Tsunami *t, - uint32_t bus_num, uint32_t dev_num, uint32_t func_num, - Bus *host_bus, Tick pio_latency, HierParams *hier); + struct Params : public PciDev::Params + { + /** Array of disk objects */ + std::vector<IdeDisk *> disks; + Bus *host_bus; + Tick pio_latency; + HierParams *hier; + }; + const Params *params() const { return (const Params *)_params; } - /** - * Deletes the connected devices. - */ + public: + IdeController(Params *p); ~IdeController(); virtual void WriteConfig(int offset, int size, uint32_t data); virtual void ReadConfig(int offset, int size, uint8_t *data); - void intrPost(); - void intrClear(); - void setDmaComplete(IdeDisk *disk); /** diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc index f3760bd5e..073c10436 100644 --- a/dev/ide_disk.cc +++ b/dev/ide_disk.cc @@ -177,7 +177,7 @@ Addr IdeDisk::pciToDma(Addr pciAddr) { if (ctrl) - return ctrl->tsunami->pchip->translatePciToDma(pciAddr); + return ctrl->plat->pciToDma(pciAddr); else panic("Access to unset controller!\n"); } diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc index 4d0b93ab9..401599126 100644 --- a/dev/ns_gige.cc +++ b/dev/ns_gige.cc @@ -41,7 +41,6 @@ #include "dev/etherlink.hh" #include "dev/ns_gige.hh" #include "dev/pciconfigall.hh" -#include "dev/tsunami_cchip.hh" #include "mem/bus/bus.hh" #include "mem/bus/dma_interface.hh" #include "mem/bus/pio_interface.hh" @@ -51,7 +50,7 @@ #include "sim/builder.hh" #include "sim/debug.hh" #include "sim/host.hh" -#include "sim/sim_stats.hh" +#include "sim/stats.hh" #include "targetarch/vtophys.hh" const char *NsRxStateStrings[] = @@ -92,64 +91,62 @@ using namespace Net; // // NSGigE PCI Device // -NSGigE::NSGigE(const std::string &name, IntrControl *i, Tick intr_delay, - PhysicalMemory *pmem, Tick tx_delay, Tick rx_delay, - MemoryController *mmu, HierParams *hier, Bus *header_bus, - Bus *payload_bus, Tick pio_latency, bool dma_desc_free, - bool dma_data_free, Tick dma_read_delay, Tick dma_write_delay, - Tick dma_read_factor, Tick dma_write_factor, PciConfigAll *cf, - PciConfigData *cd, Tsunami *t, uint32_t bus, uint32_t dev, - uint32_t func, bool rx_filter, EthAddr eaddr, - uint32_t tx_fifo_size, uint32_t rx_fifo_size) - : PciDev(name, mmu, cf, cd, bus, dev, func), tsunami(t), ioEnable(false), - maxTxFifoSize(tx_fifo_size), maxRxFifoSize(rx_fifo_size), +NSGigE::NSGigE(Params *p) + : PciDev(p), ioEnable(false), + txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size), txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL), txXferLen(0), rxXferLen(0), txState(txIdle), txEnable(false), - CTDD(false), txFifoAvail(tx_fifo_size), + CTDD(false), txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), - rxEnable(false), CRDD(false), rxPktBytes(0), rxFifoCnt(0), + rxEnable(false), CRDD(false), rxPktBytes(0), rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), rxDmaReadEvent(this), rxDmaWriteEvent(this), txDmaReadEvent(this), txDmaWriteEvent(this), - dmaDescFree(dma_desc_free), dmaDataFree(dma_data_free), - txDelay(tx_delay), rxDelay(rx_delay), rxKickTick(0), txKickTick(0), - txEvent(this), rxFilterEnable(rx_filter), acceptBroadcast(false), + dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free), + txDelay(p->tx_delay), rxDelay(p->rx_delay), + rxKickTick(0), txKickTick(0), + txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false), acceptMulticast(false), acceptUnicast(false), acceptPerfect(false), acceptArp(false), - physmem(pmem), intctrl(i), intrTick(0), cpuPendingIntr(false), + physmem(p->pmem), intrTick(0), cpuPendingIntr(false), intrEvent(0), interface(0) { - if (header_bus) { - pioInterface = newPioInterface(name, hier, header_bus, this, + if (p->header_bus) { + pioInterface = newPioInterface(name(), p->hier, + p->header_bus, this, &NSGigE::cacheAccess); - pioLatency = pio_latency * header_bus->clockRatio; + pioLatency = p->pio_latency * p->header_bus->clockRatio; - if (payload_bus) - dmaInterface = new DMAInterface<Bus>(name + ".dma", - header_bus, payload_bus, 1); + if (p->payload_bus) + dmaInterface = new DMAInterface<Bus>(name() + ".dma", + p->header_bus, + p->payload_bus, 1); else - dmaInterface = new DMAInterface<Bus>(name + ".dma", - header_bus, header_bus, 1); - } else if (payload_bus) { - pioInterface = newPioInterface(name, hier, payload_bus, this, + dmaInterface = new DMAInterface<Bus>(name() + ".dma", + p->header_bus, + p->header_bus, 1); + } else if (p->payload_bus) { + pioInterface = newPioInterface(name(), p->hier, + p->payload_bus, this, &NSGigE::cacheAccess); - pioLatency = pio_latency * payload_bus->clockRatio; + pioLatency = p->pio_latency * p->payload_bus->clockRatio; - dmaInterface = new DMAInterface<Bus>(name + ".dma", payload_bus, - payload_bus, 1); + dmaInterface = new DMAInterface<Bus>(name() + ".dma", + p->payload_bus, + p->payload_bus, 1); } - intrDelay = US2Ticks(intr_delay); - dmaReadDelay = dma_read_delay; - dmaWriteDelay = dma_write_delay; - dmaReadFactor = dma_read_factor; - dmaWriteFactor = dma_write_factor; + intrDelay = US2Ticks(p->intr_delay); + dmaReadDelay = p->dma_read_delay; + dmaWriteDelay = p->dma_write_delay; + dmaReadFactor = p->dma_read_factor; + dmaWriteFactor = p->dma_write_factor; regsReset(); - memcpy(&rom.perfectMatch, eaddr.bytes(), ETH_ADDR_LEN); + memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN); } NSGigE::~NSGigE() @@ -339,7 +336,7 @@ NSGigE::WriteConfig(int offset, int size, uint32_t data) if (pioInterface) pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); - BARAddrs[0] &= PA_UNCACHED_MASK; + BARAddrs[0] &= EV5::PAddrUncachedMask; } break; case PCI0_BASE_ADDR1: @@ -347,7 +344,7 @@ NSGigE::WriteConfig(int offset, int size, uint32_t data) if (pioInterface) pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1])); - BARAddrs[1] &= PA_UNCACHED_MASK; + BARAddrs[1] &= EV5::PAddrUncachedMask; } break; } @@ -1028,8 +1025,8 @@ NSGigE::cpuInterrupt() // Send interrupt cpuPendingIntr = true; - DPRINTF(EthernetIntr, "posting cchip interrupt\n"); - tsunami->postPciInt(configData->config.hdr.pci0.interruptLine); + DPRINTF(EthernetIntr, "posting interrupt\n"); + intrPost(); } } @@ -1048,8 +1045,8 @@ NSGigE::cpuIntrClear() cpuPendingIntr = false; - DPRINTF(EthernetIntr, "clearing cchip interrupt\n"); - tsunami->clearPciInt(configData->config.hdr.pci0.interruptLine); + DPRINTF(EthernetIntr, "clearing interrupt\n"); + intrClear(); } bool @@ -1063,7 +1060,6 @@ NSGigE::txReset() DPRINTF(Ethernet, "transmit reset\n"); CTDD = false; - txFifoAvail = maxTxFifoSize; txEnable = false;; txFragPtr = 0; assert(txDescCnt == 0); @@ -1079,7 +1075,6 @@ NSGigE::rxReset() CRDD = false; assert(rxPktBytes == 0); - rxFifoCnt = 0; rxEnable = false; rxFragPtr = 0; assert(rxDescCnt == 0); @@ -1349,9 +1344,7 @@ NSGigE::rxKick() // Must clear the value before popping to decrement the // reference count - rxFifo.front() = NULL; - rxFifo.pop_front(); - rxFifoCnt -= rxPacket->length; + rxFifo.pop(); } @@ -1539,7 +1532,7 @@ NSGigE::transmit() } DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n", - maxTxFifoSize - txFifoAvail); + txFifo.size()); if (interface->sendPacket(txFifo.front())) { #if TRACING_ON if (DTRACE(Ethernet)) { @@ -1559,12 +1552,9 @@ NSGigE::transmit() txBytes += txFifo.front()->length; txPackets++; - txFifoAvail += txFifo.front()->length; - DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", - txFifoAvail); - txFifo.front() = NULL; - txFifo.pop_front(); + txFifo.avail()); + txFifo.pop(); /* * normally do a writeback of the descriptor here, and ONLY @@ -1832,7 +1822,7 @@ NSGigE::txKick() // this is just because the receive can't handle a // packet bigger want to make sure assert(txPacket->length <= 1514); - txFifo.push_back(txPacket); + txFifo.push(txPacket); /* * this following section is not tqo spec, but @@ -1878,7 +1868,7 @@ NSGigE::txKick() } } else { DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); - if (txFifoAvail) { + if (!txFifo.full()) { txState = txFragRead; /* @@ -1887,7 +1877,7 @@ NSGigE::txKick() * is not enough room in the fifo, just whatever room * is left in the fifo */ - txXferLen = min<uint32_t>(txDescCnt, txFifoAvail); + txXferLen = min<uint32_t>(txDescCnt, txFifo.avail()); txDmaAddr = txFragPtr & 0x3fffffff; txDmaData = txPacketBufPtr; @@ -1913,7 +1903,6 @@ NSGigE::txKick() txPacketBufPtr += txXferLen; txFragPtr += txXferLen; txDescCnt -= txXferLen; - txFifoAvail -= txXferLen; txState = txFifoBlock; break; @@ -1982,7 +1971,7 @@ NSGigE::transferDone() } bool -NSGigE::rxFilter(PacketPtr &packet) +NSGigE::rxFilter(const PacketPtr &packet) { EthPtr eth = packet; bool drop = true; @@ -2022,13 +2011,13 @@ NSGigE::rxFilter(PacketPtr &packet) } bool -NSGigE::recvPacket(PacketPtr &packet) +NSGigE::recvPacket(PacketPtr packet) { rxBytes += packet->length; rxPackets++; DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n", - maxRxFifoSize - rxFifoCnt); + rxFifo.avail()); if (!rxEnable) { DPRINTF(Ethernet, "receive disabled...packet dropped\n"); @@ -2043,15 +2032,14 @@ NSGigE::recvPacket(PacketPtr &packet) return true; } - if ((rxFifoCnt + packet->length) >= maxRxFifoSize) { + if (rxFifo.avail() < packet->length) { DPRINTF(Ethernet, "packet will not fit in receive buffer...packet dropped\n"); devIntrPost(ISR_RXORN); return false; } - rxFifo.push_back(packet); - rxFifoCnt += packet->length; + rxFifo.push(packet); interface->recvDone(); rxKick(); @@ -2122,23 +2110,8 @@ NSGigE::serialize(ostream &os) /* * Serialize the data Fifos */ - int txNumPkts = txFifo.size(); - SERIALIZE_SCALAR(txNumPkts); - int i = 0; - pktiter_t end = txFifo.end(); - for (pktiter_t p = txFifo.begin(); p != end; ++p) { - nameOut(os, csprintf("%s.txFifo%d", name(), i++)); - (*p)->serialize(os); - } - - int rxNumPkts = rxFifo.size(); - SERIALIZE_SCALAR(rxNumPkts); - i = 0; - end = rxFifo.end(); - for (pktiter_t p = rxFifo.begin(); p != end; ++p) { - nameOut(os, csprintf("%s.rxFifo%d", name(), i++)); - (*p)->serialize(os); - } + rxFifo.serialize("rxFifo", os); + txFifo.serialize("txFifo", os); /* * Serialize the various helper variables @@ -2146,8 +2119,7 @@ NSGigE::serialize(ostream &os) bool txPacketExists = txPacket; SERIALIZE_SCALAR(txPacketExists); if (txPacketExists) { - nameOut(os, csprintf("%s.txPacket", name())); - txPacket->serialize(os); + txPacket->serialize("txPacket", os); uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); SERIALIZE_SCALAR(txPktBufPtr); } @@ -2155,8 +2127,7 @@ NSGigE::serialize(ostream &os) bool rxPacketExists = rxPacket; SERIALIZE_SCALAR(rxPacketExists); if (rxPacketExists) { - nameOut(os, csprintf("%s.rxPacket", name())); - rxPacket->serialize(os); + rxPacket->serialize("rxPacket", os); uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); SERIALIZE_SCALAR(rxPktBufPtr); } @@ -2183,7 +2154,6 @@ NSGigE::serialize(ostream &os) SERIALIZE_SCALAR(txState); SERIALIZE_SCALAR(txEnable); SERIALIZE_SCALAR(CTDD); - SERIALIZE_SCALAR(txFifoAvail); SERIALIZE_SCALAR(txFragPtr); SERIALIZE_SCALAR(txDescCnt); int txDmaState = this->txDmaState; @@ -2197,7 +2167,6 @@ NSGigE::serialize(ostream &os) SERIALIZE_SCALAR(rxEnable); SERIALIZE_SCALAR(CRDD); SERIALIZE_SCALAR(rxPktBytes); - SERIALIZE_SCALAR(rxFifoCnt); SERIALIZE_SCALAR(rxDescCnt); int rxDmaState = this->rxDmaState; SERIALIZE_SCALAR(rxDmaState); @@ -2279,22 +2248,8 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) /* * unserialize the data fifos */ - int txNumPkts; - UNSERIALIZE_SCALAR(txNumPkts); - int i; - for (i = 0; i < txNumPkts; ++i) { - PacketPtr p = new PacketData; - p->unserialize(cp, csprintf("%s.rxFifo%d", section, i)); - txFifo.push_back(p); - } - - int rxNumPkts; - UNSERIALIZE_SCALAR(rxNumPkts); - for (i = 0; i < rxNumPkts; ++i) { - PacketPtr p = new PacketData; - p->unserialize(cp, csprintf("%s.rxFifo%d", section, i)); - rxFifo.push_back(p); - } + rxFifo.unserialize("rxFifo", cp, section); + txFifo.unserialize("txFifo", cp, section); /* * unserialize the various helper variables @@ -2303,7 +2258,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(txPacketExists); if (txPacketExists) { txPacket = new PacketData; - txPacket->unserialize(cp, csprintf("%s.txPacket", section)); + txPacket->unserialize("txPacket", cp, section); uint32_t txPktBufPtr; UNSERIALIZE_SCALAR(txPktBufPtr); txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; @@ -2315,7 +2270,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) rxPacket = 0; if (rxPacketExists) { rxPacket = new PacketData; - rxPacket->unserialize(cp, csprintf("%s.rxPacket", section)); + rxPacket->unserialize("rxPacket", cp, section); uint32_t rxPktBufPtr; UNSERIALIZE_SCALAR(rxPktBufPtr); rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; @@ -2345,7 +2300,6 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) this->txState = (TxState) txState; UNSERIALIZE_SCALAR(txEnable); UNSERIALIZE_SCALAR(CTDD); - UNSERIALIZE_SCALAR(txFifoAvail); UNSERIALIZE_SCALAR(txFragPtr); UNSERIALIZE_SCALAR(txDescCnt); int txDmaState; @@ -2361,7 +2315,6 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(rxEnable); UNSERIALIZE_SCALAR(CRDD); UNSERIALIZE_SCALAR(rxPktBytes); - UNSERIALIZE_SCALAR(rxFifoCnt); UNSERIALIZE_SCALAR(rxDescCnt); int rxDmaState; UNSERIALIZE_SCALAR(rxDmaState); @@ -2450,7 +2403,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) Param<Tick> tx_delay; Param<Tick> rx_delay; - SimObjectParam<IntrControl *> intr_ctrl; Param<Tick> intr_delay; SimObjectParam<MemoryController *> mmu; SimObjectParam<PhysicalMemory *> physmem; @@ -2468,7 +2420,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) Param<Tick> dma_write_factor; SimObjectParam<PciConfigAll *> configspace; SimObjectParam<PciConfigData *> configdata; - SimObjectParam<Tsunami *> tsunami; + SimObjectParam<Platform *> platform; Param<uint32_t> pci_bus; Param<uint32_t> pci_dev; Param<uint32_t> pci_func; @@ -2481,7 +2433,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000), INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000), - INIT_PARAM(intr_ctrl, "Interrupt Controller"), INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0), INIT_PARAM(mmu, "Memory Controller"), INIT_PARAM(physmem, "Physical Memory"), @@ -2500,7 +2451,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0), INIT_PARAM(configspace, "PCI Configspace"), INIT_PARAM(configdata, "PCI Config data"), - INIT_PARAM(tsunami, "Tsunami"), + INIT_PARAM(platform, "Platform"), INIT_PARAM(pci_bus, "PCI bus"), INIT_PARAM(pci_dev, "PCI device number"), INIT_PARAM(pci_func, "PCI function code"), @@ -2512,14 +2463,36 @@ END_INIT_SIM_OBJECT_PARAMS(NSGigE) CREATE_SIM_OBJECT(NSGigE) { - return new NSGigE(getInstanceName(), intr_ctrl, intr_delay, - physmem, tx_delay, rx_delay, mmu, hier, header_bus, - payload_bus, pio_latency, dma_desc_free, dma_data_free, - dma_read_delay, dma_write_delay, dma_read_factor, - dma_write_factor, configspace, configdata, - tsunami, pci_bus, pci_dev, pci_func, rx_filter, - EthAddr((string)hardware_address), - tx_fifo_size, rx_fifo_size); + NSGigE::Params *params = new NSGigE::Params; + + params->name = getInstanceName(); + params->mmu = mmu; + params->configSpace = configspace; + params->configData = configdata; + params->plat = platform; + params->busNum = pci_bus; + params->deviceNum = pci_dev; + params->functionNum = pci_func; + + params->intr_delay = intr_delay; + params->pmem = physmem; + params->tx_delay = tx_delay; + params->rx_delay = rx_delay; + params->hier = hier; + params->header_bus = header_bus; + params->payload_bus = payload_bus; + params->pio_latency = pio_latency; + params->dma_desc_free = dma_desc_free; + params->dma_data_free = dma_data_free; + params->dma_read_delay = dma_read_delay; + params->dma_write_delay = dma_write_delay; + params->dma_read_factor = dma_read_factor; + params->dma_write_factor = dma_write_factor; + params->rx_filter = rx_filter; + params->eaddr = hardware_address; + params->tx_fifo_size = tx_fifo_size; + params->rx_fifo_size = rx_fifo_size; + return new NSGigE(params); } REGISTER_SIM_OBJECT("NSGigE", NSGigE) diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh index 60dcf3fc2..90711d63f 100644 --- a/dev/ns_gige.hh +++ b/dev/ns_gige.hh @@ -41,7 +41,7 @@ #include "dev/io_device.hh" #include "dev/ns_gige_reg.h" #include "dev/pcidev.hh" -#include "dev/tsunami.hh" +#include "dev/pktfifo.hh" #include "mem/bus/bus.hh" #include "sim/eventq.hh" @@ -139,10 +139,6 @@ class NSGigE : public PciDev }; private: - /** pointer to the chipset */ - Tsunami *tsunami; - - private: Addr addr; static const Addr size = sizeof(dp_regs); @@ -163,10 +159,8 @@ class NSGigE : public PciDev /*** BASIC STRUCTURES FOR TX/RX ***/ /* Data FIFOs */ - pktbuf_t txFifo; - uint32_t maxTxFifoSize; - pktbuf_t rxFifo; - uint32_t maxRxFifoSize; + PacketFifo txFifo; + PacketFifo rxFifo; /** various helper vars */ PacketPtr txPacket; @@ -188,8 +182,6 @@ class NSGigE : public PciDev /** Current Transmit Descriptor Done */ bool CTDD; - /** current amt of free space in txDataFifo in bytes */ - uint32_t txFifoAvail; /** halt the tx state machine after next packet */ bool txHalt; /** ptr to the next byte in the current fragment */ @@ -206,8 +198,6 @@ class NSGigE : public PciDev bool CRDD; /** num of bytes in the current packet being drained from rxDataFifo */ uint32_t rxPktBytes; - /** number of bytes in the rxFifo */ - uint32_t rxFifoCnt; /** halt the rx state machine after current packet */ bool rxHalt; /** ptr to the next byte in current fragment */ @@ -300,7 +290,7 @@ class NSGigE : public PciDev * receive address filter */ bool rxFilterEnable; - bool rxFilter(PacketPtr &packet); + bool rxFilter(const PacketPtr &packet); bool acceptBroadcast; bool acceptMulticast; bool acceptUnicast; @@ -330,16 +320,31 @@ class NSGigE : public PciDev NSGigEInt *interface; public: - NSGigE(const std::string &name, IntrControl *i, Tick intr_delay, - PhysicalMemory *pmem, Tick tx_delay, Tick rx_delay, - MemoryController *mmu, HierParams *hier, Bus *header_bus, - Bus *payload_bus, Tick pio_latency, bool dma_desc_free, - bool dma_data_free, Tick dma_read_delay, Tick dma_write_delay, - Tick dma_read_factor, Tick dma_write_factor, PciConfigAll *cf, - PciConfigData *cd, Tsunami *t, uint32_t bus, uint32_t dev, - uint32_t func, bool rx_filter, Net::EthAddr eaddr, - uint32_t tx_fifo_size, uint32_t rx_fifo_size); + struct Params : public PciDev::Params + { + PhysicalMemory *pmem; + HierParams *hier; + Bus *header_bus; + Bus *payload_bus; + Tick intr_delay; + Tick tx_delay; + Tick rx_delay; + Tick pio_latency; + bool dma_desc_free; + bool dma_data_free; + Tick dma_read_delay; + Tick dma_write_delay; + Tick dma_read_factor; + Tick dma_write_factor; + bool rx_filter; + Net::EthAddr eaddr; + uint32_t tx_fifo_size; + uint32_t rx_fifo_size; + }; + + NSGigE(Params *params); ~NSGigE(); + const Params *params() const { return (const Params *)_params; } virtual void WriteConfig(int offset, int size, uint32_t data); virtual void ReadConfig(int offset, int size, uint8_t *data); @@ -350,7 +355,7 @@ class NSGigE : public PciDev bool cpuIntrPending() const; void cpuIntrAck() { cpuIntrClear(); } - bool recvPacket(PacketPtr &packet); + bool recvPacket(PacketPtr packet); void transferDone(); void setInterface(NSGigEInt *i) { assert(!interface); interface = i; } @@ -397,7 +402,7 @@ class NSGigEInt : public EtherInt NSGigEInt(const std::string &name, NSGigE *d) : EtherInt(name), dev(d) { dev->setInterface(this); } - virtual bool recvPacket(PacketPtr &pkt) { return dev->recvPacket(pkt); } + virtual bool recvPacket(PacketPtr pkt) { return dev->recvPacket(pkt); } virtual void sendDone() { dev->transferDone(); } }; diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc index 6fee30c10..d5302d9ad 100644 --- a/dev/pciconfigall.cc +++ b/dev/pciconfigall.cc @@ -71,7 +71,7 @@ PciConfigAll::read(MemReqPtr &req, uint8_t *data) DPRINTF(PciConfigAll, "read va=%#x size=%d\n", req->vaddr, req->size); - Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)); + Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); int device = (daddr >> 11) & 0x1F; int func = (daddr >> 8) & 0x7; @@ -115,7 +115,7 @@ PciConfigAll::read(MemReqPtr &req, uint8_t *data) Fault PciConfigAll::write(MemReqPtr &req, const uint8_t *data) { - Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)); + Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); int device = (daddr >> 11) & 0x1F; int func = (daddr >> 8) & 0x7; diff --git a/dev/pcidev.cc b/dev/pcidev.cc index f0ceb40f2..d156b6a02 100644 --- a/dev/pcidev.cc +++ b/dev/pcidev.cc @@ -50,36 +50,38 @@ using namespace std; -PciDev::PciDev(const string &name, MemoryController *mmu, PciConfigAll *cf, - PciConfigData *cd, uint32_t bus, uint32_t dev, uint32_t func) - : DmaDevice(name), mmu(mmu), configSpace(cf), configData(cd), busNum(bus), - deviceNum(dev), functionNum(func) +PciDev::PciDev(Params *p) + : DmaDevice(p->name), _params(p), plat(p->plat), configData(p->configData) { // copy the config data from the PciConfigData object - if (cd) { - memcpy(config.data, cd->config.data, sizeof(config.data)); - memcpy(BARSize, cd->BARSize, sizeof(BARSize)); - memcpy(BARAddrs, cd->BARAddrs, sizeof(BARAddrs)); + if (configData) { + memcpy(config.data, configData->config.data, sizeof(config.data)); + memcpy(BARSize, configData->BARSize, sizeof(BARSize)); + memcpy(BARAddrs, configData->BARAddrs, sizeof(BARAddrs)); } else panic("NULL pointer to configuration data"); // Setup pointer in config space to point to this entry - if (cf->deviceExists(dev,func)) - panic("Two PCI devices occuping same dev: %#x func: %#x", dev, func); + if (p->configSpace->deviceExists(p->deviceNum, p->functionNum)) + panic("Two PCI devices occuping same dev: %#x func: %#x", + p->deviceNum, p->functionNum); else - cf->registerDevice(dev, func, this); + p->configSpace->registerDevice(p->deviceNum, p->functionNum, this); } void PciDev::ReadConfig(int offset, int size, uint8_t *data) { + if (offset >= PCI_DEVICE_SPECIFIC) + panic("Device specific PCI config space not implemented!\n"); + switch(size) { case sizeof(uint32_t): memcpy((uint8_t*)data, config.data + offset, sizeof(uint32_t)); *(uint32_t*)data = htoa(*(uint32_t*)data); DPRINTF(PCIDEV, "read device: %#x function: %#x register: %#x %d bytes: data: %#x\n", - deviceNum, functionNum, offset, size, + params()->deviceNum, params()->functionNum, offset, size, *(uint32_t*)(config.data + offset)); break; @@ -88,7 +90,7 @@ PciDev::ReadConfig(int offset, int size, uint8_t *data) *(uint16_t*)data = htoa(*(uint16_t*)data); DPRINTF(PCIDEV, "read device: %#x function: %#x register: %#x %d bytes: data: %#x\n", - deviceNum, functionNum, offset, size, + params()->deviceNum, params()->functionNum, offset, size, *(uint16_t*)(config.data + offset)); break; @@ -96,7 +98,7 @@ PciDev::ReadConfig(int offset, int size, uint8_t *data) memcpy((uint8_t*)data, config.data + offset, sizeof(uint8_t)); DPRINTF(PCIDEV, "read device: %#x function: %#x register: %#x %d bytes: data: %#x\n", - deviceNum, functionNum, offset, size, + params()->deviceNum, params()->functionNum, offset, size, (uint16_t)(*(uint8_t*)(config.data + offset))); break; @@ -108,6 +110,9 @@ PciDev::ReadConfig(int offset, int size, uint8_t *data) void PciDev::WriteConfig(int offset, int size, uint32_t data) { + if (offset >= PCI_DEVICE_SPECIFIC) + panic("Device specific PCI config space not implemented!\n"); + uint32_t barnum; union { @@ -119,7 +124,8 @@ PciDev::WriteConfig(int offset, int size, uint32_t data) DPRINTF(PCIDEV, "write device: %#x function: %#x reg: %#x size: %d data: %#x\n", - deviceNum, functionNum, offset, size, word_value); + params()->deviceNum, params()->functionNum, offset, size, + word_value); barnum = (offset - PCI0_BASE_ADDR0) >> 2; @@ -177,9 +183,12 @@ PciDev::WriteConfig(int offset, int size, uint32_t data) (htoa(config.data[offset]) & 0xF)); } } else { + MemoryController *mmu = params()->mmu; + // This is I/O Space, bottom two bits are read only if(htoa(config.data[offset]) & 0x1) { - *(uint32_t *)&config.data[offset] = htoa((word_value & ~0x3) | + *(uint32_t *)&config.data[offset] = + htoa((word_value & ~0x3) | (htoa(config.data[offset]) & 0x3)); if (word_value & ~0x1) { @@ -201,7 +210,8 @@ PciDev::WriteConfig(int offset, int size, uint32_t data) } else { // This is memory space, bottom four bits are read only - *(uint32_t *)&config.data[offset] = htoa((word_value & ~0xF) | + *(uint32_t *)&config.data[offset] = + htoa((word_value & ~0xF) | (htoa(config.data[offset]) & 0xF)); if (word_value & ~0x3) { @@ -265,7 +275,7 @@ PciDev::unserialize(Checkpoint *cp, const std::string §ion) // Add the MMU mappings for the BARs for (int i=0; i < 6; i++) { if (BARAddrs[i] != 0) - mmu->add_child(this, RangeSize(BARAddrs[i], BARSize[i])); + params()->mmu->add_child(this, RangeSize(BARAddrs[i], BARSize[i])); } } diff --git a/dev/pcidev.hh b/dev/pcidev.hh index c0fe47ac4..73d2e3c44 100644 --- a/dev/pcidev.hh +++ b/dev/pcidev.hh @@ -30,11 +30,12 @@ * Interface for devices using PCI configuration */ -#ifndef __PCI_DEV_HH__ -#define __PCI_DEV_HH__ +#ifndef __DEV_PCIDEV_HH__ +#define __DEV_PCIDEV_HH__ -#include "dev/pcireg.h" #include "dev/io_device.hh" +#include "dev/pcireg.h" +#include "dev/platform.hh" class PciConfigAll; class MemoryController; @@ -78,29 +79,43 @@ class PciConfigData : public SimObject class PciDev : public DmaDevice { protected: - MemoryController *mmu; - /** A pointer to the configspace all object that calls - * us when a read comes to this particular device/function. - */ - PciConfigAll *configSpace; + struct Params; + Params *_params; - /** - * A pointer to the object that contains the first 64 bytes of - * config space - */ - PciConfigData *configData; + public: + struct Params + { + std::string name; + Platform *plat; + MemoryController *mmu; + + /** + * A pointer to the configspace all object that calls us when + * a read comes to this particular device/function. + */ + PciConfigAll *configSpace; - /** The bus number we are on */ - uint32_t busNum; + /** + * A pointer to the object that contains the first 64 bytes of + * config space + */ + PciConfigData *configData; - /** The device number we have */ - uint32_t deviceNum; + /** The bus number we are on */ + uint32_t busNum; - /** The function number */ - uint32_t functionNum; + /** The device number we have */ + uint32_t deviceNum; - /** The current config space. Unlike the PciConfigData this is updated - * during simulation while continues to refelect what was in the config file. + /** The function number */ + uint32_t functionNum; + }; + const Params *params() const { return _params; } + + protected: + /** The current config space. Unlike the PciConfigData this is + * updated during simulation while continues to refelect what was + * in the config file. */ PCIConfig config; @@ -110,21 +125,29 @@ class PciDev : public DmaDevice /** The current address mapping of the BARs */ Addr BARAddrs[6]; + protected: + Platform *plat; + PciConfigData *configData; + + public: + Addr pciToDma(Addr pciAddr) const + { return plat->pciToDma(pciAddr); } + + void + intrPost() + { plat->postPciInt(configData->config.hdr.pci0.interruptLine); } + + void + intrClear() + { plat->clearPciInt(configData->config.hdr.pci0.interruptLine); } + public: /** - * Constructor for PCI Dev. This function copies data from the config file - * object PCIConfigData and registers the device with a PciConfigAll object. - * @param name name of the object - * @param mmu a pointer to the memory controller - * @param cf a pointer to the config space object that this device need to - * register with - * @param cd A pointer to the config space values specified in the conig file - * @param bus the bus this device is on - * @param dev the device id of this device - * @param func the function number of this device + * Constructor for PCI Dev. This function copies data from the + * config file object PCIConfigData and registers the device with + * a PciConfigAll object. */ - PciDev(const std::string &name, MemoryController *mmu, PciConfigAll *cf, - PciConfigData *cd, uint32_t bus, uint32_t dev, uint32_t func); + PciDev(Params *params); virtual Fault read(MemReqPtr &req, uint8_t *data) { return No_Fault; @@ -168,4 +191,4 @@ class PciDev : public DmaDevice virtual void unserialize(Checkpoint *cp, const std::string §ion); }; -#endif // __PCI_DEV_HH__ +#endif // __DEV_PCIDEV_HH__ diff --git a/dev/pktfifo.cc b/dev/pktfifo.cc new file mode 100644 index 000000000..cf09ae910 --- /dev/null +++ b/dev/pktfifo.cc @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2002-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "base/misc.hh" +#include "dev/pktfifo.hh" + +using namespace std; + +void +PacketFifo::serialize(const string &base, ostream &os) +{ + paramOut(os, base + ".size", _size); + paramOut(os, base + ".maxsize", _maxsize); + paramOut(os, base + ".packets", fifo.size()); + + int i = 0; + std::list<PacketPtr>::iterator p = fifo.begin(); + std::list<PacketPtr>::iterator end = fifo.end(); + while (p != end) { + (*p)->serialize(csprintf("%s.packet%d", base, i), os); + ++p; + ++i; + } +} + +void +PacketFifo::unserialize(const string &base, Checkpoint *cp, + const string §ion) +{ + paramIn(cp, section, base + ".size", _size); + paramIn(cp, section, base + ".maxsize", _maxsize); + int fifosize; + paramIn(cp, section, base + ".packets", fifosize); + + fifo.clear(); + fifo.resize(fifosize); + + for (int i = 0; i < fifosize; ++i) { + PacketPtr p = new PacketData; + p->unserialize(csprintf("%s.packet%d", base, i), cp, section); + fifo.push_back(p); + } +} diff --git a/dev/pktfifo.hh b/dev/pktfifo.hh new file mode 100644 index 000000000..a54a49996 --- /dev/null +++ b/dev/pktfifo.hh @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2002-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __DEV_PKTFIFO_HH__ +#define __DEV_PKTFIFO_HH__ + +#include <iosfwd> +#include <list> +#include <string> + +#include "dev/etherpkt.hh" +#include "sim/serialize.hh" + +class Checkpoint; +class PacketFifo +{ + protected: + std::list<PacketPtr> fifo; + int _maxsize; + int _size; + + public: + explicit PacketFifo(int max) : _maxsize(max), _size(0) {} + virtual ~PacketFifo() {} + + int maxsize() const { return _maxsize; } + int packets() const { return fifo.size(); } + int size() const { return _size; } + int avail() const { return _maxsize - _size; } + bool empty() const { return _size == 0; } + bool full() const { return _size >= _maxsize; } + + bool push(PacketPtr ptr) + { + if (avail() < ptr->length) + return false; + + _size += ptr->length; + fifo.push_back(ptr); + return true; + } + + PacketPtr front() { return fifo.front(); } + + void pop() + { + if (empty()) + return; + + _size -= fifo.front()->length; + fifo.front() = NULL; + fifo.pop_front(); + } + + void clear() + { + fifo.clear(); + _size = 0; + } + +/** + * Serialization stuff + */ + public: + void serialize(const std::string &base, std::ostream &os); + void unserialize(const std::string &base, + Checkpoint *cp, const std::string §ion); +}; + +#endif // __DEV_PKTFIFO_HH__ diff --git a/dev/platform.cc b/dev/platform.cc index 8515d543a..cf012352b 100644 --- a/dev/platform.cc +++ b/dev/platform.cc @@ -32,5 +32,23 @@ using namespace std; +void +Platform::postPciInt(int line) +{ + panic("No PCI interrupt support in platform."); +} + +void +Platform::clearPciInt(int line) +{ + panic("No PCI interrupt support in platform."); +} + +Addr +Platform::pciToDma(Addr pciAddr) const +{ + panic("No PCI dma support in platform."); +} + DEFINE_SIM_OBJECT_CLASS_NAME("Platform", Platform) diff --git a/dev/platform.hh b/dev/platform.hh index 0c90e06ba..717e49411 100644 --- a/dev/platform.hh +++ b/dev/platform.hh @@ -35,6 +35,7 @@ #define __PLATFORM_HH_ #include "sim/sim_object.hh" +#include "targetarch/isa_traits.hh" class PciConfigAll; class IntrControl; @@ -65,8 +66,9 @@ class Platform : public SimObject virtual void postConsoleInt() = 0; virtual void clearConsoleInt() = 0; virtual Tick intrFrequency() = 0; - virtual void postPciInt(int line) = 0; - virtual void clearPciInt(int line) = 0; + virtual void postPciInt(int line); + virtual void clearPciInt(int line); + virtual Addr pciToDma(Addr pciAddr) const; }; #endif // __PLATFORM_HH_ diff --git a/dev/simconsole.cc b/dev/simconsole.cc index b2afb3f84..d8d890e15 100644 --- a/dev/simconsole.cc +++ b/dev/simconsole.cc @@ -45,12 +45,11 @@ #include "base/misc.hh" #include "base/socket.hh" #include "base/trace.hh" +#include "dev/platform.hh" #include "dev/simconsole.hh" +#include "dev/uart.hh" #include "mem/functional_mem/memory_control.hh" #include "sim/builder.hh" -#include "targetarch/ev5.hh" -#include "dev/uart.hh" -#include "dev/platform.hh" using namespace std; diff --git a/dev/sinic.cc b/dev/sinic.cc new file mode 100644 index 000000000..80364ef20 --- /dev/null +++ b/dev/sinic.cc @@ -0,0 +1,1435 @@ +/* + * Copyright (c) 2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <cstdio> +#include <deque> +#include <string> + +#include "base/inet.hh" +#include "cpu/exec_context.hh" +#include "cpu/intr_control.hh" +#include "dev/dma.hh" +#include "dev/etherlink.hh" +#include "dev/sinic.hh" +#include "dev/pciconfigall.hh" +#include "mem/bus/bus.hh" +#include "mem/bus/dma_interface.hh" +#include "mem/bus/pio_interface.hh" +#include "mem/bus/pio_interface_impl.hh" +#include "mem/functional_mem/memory_control.hh" +#include "mem/functional_mem/physical_memory.hh" +#include "sim/builder.hh" +#include "sim/debug.hh" +#include "sim/eventq.hh" +#include "sim/host.hh" +#include "sim/stats.hh" +#include "targetarch/vtophys.hh" + +using namespace Net; + +namespace Sinic { + +const char *RxStateStrings[] = +{ + "rxIdle", + "rxFifoBlock", + "rxBeginCopy", + "rxCopy", + "rxCopyDone" +}; + +const char *TxStateStrings[] = +{ + "txIdle", + "txFifoBlock", + "txBeginCopy", + "txCopy", + "txCopyDone" +}; + + +/////////////////////////////////////////////////////////////////////// +// +// Sinic PCI Device +// +Base::Base(Params *p) + : PciDev(p), rxEnable(false), txEnable(false), + intrDelay(US2Ticks(p->intr_delay)), + intrTick(0), cpuIntrEnable(false), cpuPendingIntr(false), intrEvent(0), + interface(NULL) +{ +} + +Device::Device(Params *p) + : Base(p), plat(p->plat), physmem(p->physmem), + rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), + rxKickTick(0), txKickTick(0), + txEvent(this), rxDmaEvent(this), txDmaEvent(this), + dmaReadDelay(p->dma_read_delay), dmaReadFactor(p->dma_read_factor), + dmaWriteDelay(p->dma_write_delay), dmaWriteFactor(p->dma_write_factor) +{ + reset(); + + if (p->header_bus) { + pioInterface = newPioInterface(p->name, p->hier, p->header_bus, this, + &Device::cacheAccess); + + pioLatency = p->pio_latency * p->header_bus->clockRatio; + + if (p->payload_bus) + dmaInterface = new DMAInterface<Bus>(p->name + ".dma", + p->header_bus, p->payload_bus, + 1); + else + dmaInterface = new DMAInterface<Bus>(p->name + ".dma", + p->header_bus, p->header_bus, + 1); + } else if (p->payload_bus) { + pioInterface = newPioInterface(p->name, p->hier, p->payload_bus, this, + &Device::cacheAccess); + + pioLatency = p->pio_latency * p->payload_bus->clockRatio; + + dmaInterface = new DMAInterface<Bus>(p->name + ".dma", p->payload_bus, + p->payload_bus, 1); + } +} + +Device::~Device() +{} + +void +Device::regStats() +{ + rxBytes + .name(name() + ".rxBytes") + .desc("Bytes Received") + .prereq(rxBytes) + ; + + rxBandwidth + .name(name() + ".rxBandwidth") + .desc("Receive Bandwidth (bits/s)") + .precision(0) + .prereq(rxBytes) + ; + + rxPackets + .name(name() + ".rxPackets") + .desc("Number of Packets Received") + .prereq(rxBytes) + ; + + rxPacketRate + .name(name() + ".rxPPS") + .desc("Packet Reception Rate (packets/s)") + .precision(0) + .prereq(rxBytes) + ; + + rxIpPackets + .name(name() + ".rxIpPackets") + .desc("Number of IP Packets Received") + .prereq(rxBytes) + ; + + rxTcpPackets + .name(name() + ".rxTcpPackets") + .desc("Number of Packets Received") + .prereq(rxBytes) + ; + + rxUdpPackets + .name(name() + ".rxUdpPackets") + .desc("Number of UDP Packets Received") + .prereq(rxBytes) + ; + + rxIpChecksums + .name(name() + ".rxIpChecksums") + .desc("Number of rx IP Checksums done by device") + .precision(0) + .prereq(rxBytes) + ; + + rxTcpChecksums + .name(name() + ".rxTcpChecksums") + .desc("Number of rx TCP Checksums done by device") + .precision(0) + .prereq(rxBytes) + ; + + rxUdpChecksums + .name(name() + ".rxUdpChecksums") + .desc("Number of rx UDP Checksums done by device") + .precision(0) + .prereq(rxBytes) + ; + + txBytes + .name(name() + ".txBytes") + .desc("Bytes Transmitted") + .prereq(txBytes) + ; + + txBandwidth + .name(name() + ".txBandwidth") + .desc("Transmit Bandwidth (bits/s)") + .precision(0) + .prereq(txBytes) + ; + + txPackets + .name(name() + ".txPackets") + .desc("Number of Packets Transmitted") + .prereq(txBytes) + ; + + txPacketRate + .name(name() + ".txPPS") + .desc("Packet Tranmission Rate (packets/s)") + .precision(0) + .prereq(txBytes) + ; + + txIpPackets + .name(name() + ".txIpPackets") + .desc("Number of IP Packets Transmitted") + .prereq(txBytes) + ; + + txTcpPackets + .name(name() + ".txTcpPackets") + .desc("Number of TCP Packets Transmitted") + .prereq(txBytes) + ; + + txUdpPackets + .name(name() + ".txUdpPackets") + .desc("Number of Packets Transmitted") + .prereq(txBytes) + ; + + txIpChecksums + .name(name() + ".txIpChecksums") + .desc("Number of tx IP Checksums done by device") + .precision(0) + .prereq(txBytes) + ; + + txTcpChecksums + .name(name() + ".txTcpChecksums") + .desc("Number of tx TCP Checksums done by device") + .precision(0) + .prereq(txBytes) + ; + + txUdpChecksums + .name(name() + ".txUdpChecksums") + .desc("Number of tx UDP Checksums done by device") + .precision(0) + .prereq(txBytes) + ; + + txBandwidth = txBytes * Stats::constant(8) / simSeconds; + rxBandwidth = rxBytes * Stats::constant(8) / simSeconds; + txPacketRate = txPackets / simSeconds; + rxPacketRate = rxPackets / simSeconds; +} + +/** + * This is to write to the PCI general configuration registers + */ +void +Device::WriteConfig(int offset, int size, uint32_t data) +{ + switch (offset) { + case PCI0_BASE_ADDR0: + // Need to catch writes to BARs to update the PIO interface + PciDev::WriteConfig(offset, size, data); + if (BARAddrs[0] != 0) { + if (pioInterface) + pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); + + BARAddrs[0] &= EV5::PAddrUncachedMask; + } + break; + + default: + PciDev::WriteConfig(offset, size, data); + } +} + +/** + * This reads the device registers, which are detailed in the NS83820 + * spec sheet + */ +Fault +Device::read(MemReqPtr &req, uint8_t *data) +{ + assert(config.hdr.command & PCI_CMD_MSE); + + //The mask is to give you only the offset into the device register file + Addr daddr = req->paddr & 0xfff; + + if (Regs::regSize(daddr) == 0) + panic("invalid address: da=%#x pa=%#x va=%#x size=%d", + daddr, req->paddr, req->vaddr, req->size); + + if (req->size != Regs::regSize(daddr)) + panic("invalid size for reg %s: da=%#x pa=%#x va=%#x size=%d", + Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size); + + DPRINTF(EthernetPIO, "read reg=%s da=%#x pa=%#x va=%#x size=%d\n", + Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size); + + uint32_t ®32 = *(uint32_t *)data; + uint64_t ®64 = *(uint64_t *)data; + + switch (daddr) { + case Regs::Config: + reg32 = regs.Config; + break; + + case Regs::RxMaxCopy: + reg32 = regs.RxMaxCopy; + break; + + case Regs::TxMaxCopy: + reg32 = regs.TxMaxCopy; + break; + + case Regs::RxThreshold: + reg32 = regs.RxThreshold; + break; + + case Regs::TxThreshold: + reg32 = regs.TxThreshold; + break; + + case Regs::IntrStatus: + reg32 = regs.IntrStatus; + devIntrClear(); + break; + + case Regs::IntrMask: + reg32 = regs.IntrMask; + break; + + case Regs::RxData: + reg64 = regs.RxData; + break; + + case Regs::RxDone: + case Regs::RxWait: + reg64 = Regs::set_RxDone_FifoLen(regs.RxDone, + min(rxFifo.packets(), 255)); + break; + + case Regs::TxData: + reg64 = regs.TxData; + break; + + case Regs::TxDone: + case Regs::TxWait: + reg64 = Regs::set_TxDone_FifoLen(regs.TxDone, + min(txFifo.packets(), 255)); + break; + + case Regs::HwAddr: + reg64 = params()->eaddr; + break; + + default: + panic("reading write only register %s: da=%#x pa=%#x va=%#x size=%d", + Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size); + } + + DPRINTF(EthernetPIO, "read reg=%s done val=%#x\n", Regs::regName(daddr), + Regs::regSize(daddr) == 4 ? reg32 : reg64); + + return No_Fault; +} + +Fault +Device::write(MemReqPtr &req, const uint8_t *data) +{ + assert(config.hdr.command & PCI_CMD_MSE); + Addr daddr = req->paddr & 0xfff; + + if (Regs::regSize(daddr) == 0) + panic("invalid address: da=%#x pa=%#x va=%#x size=%d", + daddr, req->paddr, req->vaddr, req->size); + + if (req->size != Regs::regSize(daddr)) + panic("invalid size: reg=%s da=%#x pa=%#x va=%#x size=%d", + Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size); + + uint32_t reg32 = *(uint32_t *)data; + uint64_t reg64 = *(uint64_t *)data; + + DPRINTF(EthernetPIO, "write reg=%s val=%#x da=%#x pa=%#x va=%#x size=%d\n", + Regs::regName(daddr), Regs::regSize(daddr) == 4 ? reg32 : reg64, + daddr, req->paddr, req->vaddr, req->size); + + + switch (daddr) { + case Regs::Config: + changeConfig(reg32); + break; + + case Regs::RxThreshold: + regs.RxThreshold = reg32; + break; + + case Regs::TxThreshold: + regs.TxThreshold = reg32; + break; + + case Regs::IntrMask: + devIntrChangeMask(reg32); + break; + + case Regs::RxData: + if (rxState != rxIdle) + panic("receive machine busy with another request!"); + + regs.RxDone = 0; + regs.RxData = reg64; + if (rxEnable) { + rxState = rxFifoBlock; + rxKick(); + } + break; + + case Regs::TxData: + if (txState != txIdle) + panic("transmit machine busy with another request!"); + + regs.TxDone = 0; + regs.TxData = reg64; + if (txEnable) { + txState = txFifoBlock; + txKick(); + } + break; + + default: + panic("writing read only register %s: da=%#x pa=%#x va=%#x size=%d", + Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size); + } + + return No_Fault; +} + +void +Device::devIntrPost(uint32_t interrupts) +{ + if ((interrupts & Regs::Intr_Res)) + panic("Cannot set a reserved interrupt"); + + regs.IntrStatus |= interrupts; + + DPRINTF(EthernetIntr, + "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n", + interrupts, regs.IntrStatus, regs.IntrMask); + + if ((regs.IntrStatus & regs.IntrMask)) { + Tick when = curTick; + if ((regs.IntrStatus & regs.IntrMask & Regs::Intr_NoDelay) == 0) + when += intrDelay; + cpuIntrPost(when); + } +} + +void +Device::devIntrClear(uint32_t interrupts) +{ + if ((interrupts & Regs::Intr_Res)) + panic("Cannot clear a reserved interrupt"); + + regs.IntrStatus &= ~interrupts; + + DPRINTF(EthernetIntr, + "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n", + interrupts, regs.IntrStatus, regs.IntrMask); + + if (!(regs.IntrStatus & regs.IntrMask)) + cpuIntrClear(); +} + +void +Device::devIntrChangeMask(uint32_t newmask) +{ + if (regs.IntrMask == newmask) + return; + + regs.IntrMask = newmask; + + DPRINTF(EthernetIntr, + "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n", + regs.IntrStatus, regs.IntrMask, regs.IntrStatus & regs.IntrMask); + + if (regs.IntrStatus & regs.IntrMask) + cpuIntrPost(curTick); + else + cpuIntrClear(); +} + +void +Base::cpuIntrPost(Tick when) +{ + // If the interrupt you want to post is later than an interrupt + // already scheduled, just let it post in the coming one and don't + // schedule another. + // HOWEVER, must be sure that the scheduled intrTick is in the + // future (this was formerly the source of a bug) + /** + * @todo this warning should be removed and the intrTick code should + * be fixed. + */ + assert(when >= curTick); + assert(intrTick >= curTick || intrTick == 0); + if (!cpuIntrEnable) { + DPRINTF(EthernetIntr, "interrupts not enabled.\n", + intrTick); + return; + } + + if (when > intrTick && intrTick != 0) { + DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n", + intrTick); + return; + } + + intrTick = when; + if (intrTick < curTick) { + debug_break(); + intrTick = curTick; + } + + DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", + intrTick); + + if (intrEvent) + intrEvent->squash(); + intrEvent = new IntrEvent(this, true); + intrEvent->schedule(intrTick); +} + +void +Base::cpuInterrupt() +{ + assert(intrTick == curTick); + + // Whether or not there's a pending interrupt, we don't care about + // it anymore + intrEvent = 0; + intrTick = 0; + + // Don't send an interrupt if there's already one + if (cpuPendingIntr) { + DPRINTF(EthernetIntr, + "would send an interrupt now, but there's already pending\n"); + } else { + // Send interrupt + cpuPendingIntr = true; + + DPRINTF(EthernetIntr, "posting interrupt\n"); + intrPost(); + } +} + +void +Base::cpuIntrClear() +{ + if (!cpuPendingIntr) + return; + + if (intrEvent) { + intrEvent->squash(); + intrEvent = 0; + } + + intrTick = 0; + + cpuPendingIntr = false; + + DPRINTF(EthernetIntr, "clearing cchip interrupt\n"); + intrClear(); +} + +bool +Base::cpuIntrPending() const +{ return cpuPendingIntr; } + +void +Device::changeConfig(uint32_t newconf) +{ + uint32_t changed = regs.Config ^ newconf; + if (!changed) + return; + + regs.Config = newconf; + + if ((changed & Regs::Config_Reset)) { + assert(regs.Config & Regs::Config_Reset); + reset(); + regs.Config &= ~Regs::Config_Reset; + } + + if ((changed & Regs::Config_IntEn)) { + cpuIntrEnable = regs.Config & Regs::Config_IntEn; + if (cpuIntrEnable) { + if (regs.IntrStatus & regs.IntrMask) + cpuIntrPost(curTick); + } else { + cpuIntrClear(); + } + } + + if ((changed & Regs::Config_TxEn)) { + txEnable = regs.Config & Regs::Config_TxEn; + if (txEnable) + txKick(); + } + + if ((changed & Regs::Config_RxEn)) { + rxEnable = regs.Config & Regs::Config_RxEn; + if (rxEnable) + rxKick(); + } +} + +void +Device::reset() +{ + using namespace Regs; + memset(®s, 0, sizeof(regs)); + regs.RxMaxCopy = params()->rx_max_copy; + regs.TxMaxCopy = params()->tx_max_copy; + regs.IntrMask = Intr_TxFifo | Intr_RxFifo | Intr_RxData; + + rxState = rxIdle; + txState = txIdle; + + rxFifo.clear(); + txFifo.clear(); +} + +void +Device::rxDmaCopy() +{ + assert(rxState == rxCopy); + rxState = rxCopyDone; + physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen); + DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", + rxDmaAddr, rxDmaLen); + DDUMP(EthernetDMA, rxDmaData, rxDmaLen); +} + +void +Device::rxDmaDone() +{ + rxDmaCopy(); + rxKick(); +} + +void +Device::rxKick() +{ + DPRINTF(EthernetSM, "receive kick rxState=%s (rxFifo.size=%d)\n", + RxStateStrings[rxState], rxFifo.size()); + + if (rxKickTick > curTick) { + DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", + rxKickTick); + return; + } + + next: + switch (rxState) { + case rxIdle: + if (rxPioRequest) { + pioInterface->respond(rxPioRequest, curTick); + rxPioRequest = 0; + } + goto exit; + + case rxFifoBlock: + if (rxPacket) { + rxState = rxBeginCopy; + break; + } + + if (rxFifo.empty()) { + DPRINTF(EthernetSM, "receive waiting for data. Nothing to do.\n"); + goto exit; + } + + // Grab a new packet from the fifo. + rxPacket = rxFifo.front(); + rxPacketBufPtr = rxPacket->data; + rxPktBytes = rxPacket->length; + assert(rxPktBytes); + + rxDoneData = 0; + /* scope for variables */ { + IpPtr ip(rxPacket); + if (ip) { + rxDoneData |= Regs::RxDone_IpPacket; + rxIpChecksums++; + if (cksum(ip) != 0) { + DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); + rxDoneData |= Regs::RxDone_IpError; + } + TcpPtr tcp(ip); + UdpPtr udp(ip); + if (tcp) { + rxDoneData |= Regs::RxDone_TcpPacket; + rxTcpChecksums++; + if (cksum(tcp) != 0) { + DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); + rxDoneData |= Regs::RxDone_TcpError; + } + } else if (udp) { + rxDoneData |= Regs::RxDone_UdpPacket; + rxUdpChecksums++; + if (cksum(udp) != 0) { + DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); + rxDoneData |= Regs::RxDone_UdpError; + } + } + } + } + rxState = rxBeginCopy; + break; + + case rxBeginCopy: + rxDmaAddr = plat->pciToDma(Regs::get_RxData_Addr(regs.RxData)); + rxDmaLen = min<int>(Regs::get_RxData_Len(regs.RxData), rxPktBytes); + rxDmaData = rxPacketBufPtr; + + if (dmaInterface) { + if (!dmaInterface->busy()) { + dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, + curTick, &rxDmaEvent, true); + rxState = rxCopy; + } + goto exit; + } + + rxState = rxCopy; + if (dmaWriteDelay != 0 || dmaWriteFactor != 0) { + Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; + Tick start = curTick + dmaWriteDelay + factor; + rxDmaEvent.schedule(start); + goto exit; + } + + rxDmaCopy(); + break; + + case rxCopy: + DPRINTF(EthernetSM, "receive machine still copying\n"); + goto exit; + + case rxCopyDone: + regs.RxDone = rxDoneData | rxDmaLen; + + if (rxPktBytes == rxDmaLen) { + rxPacket = NULL; + rxFifo.pop(); + } else { + regs.RxDone |= Regs::RxDone_More; + rxPktBytes -= rxDmaLen; + rxPacketBufPtr += rxDmaLen; + } + + regs.RxDone |= Regs::RxDone_Complete; + devIntrPost(Regs::Intr_RxData); + rxState = rxIdle; + break; + + default: + panic("Invalid rxState!"); + } + + DPRINTF(EthernetSM, "entering next rxState=%s\n", + RxStateStrings[rxState]); + + goto next; + + exit: + /** + * @todo do we want to schedule a future kick? + */ + DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", + RxStateStrings[rxState]); +} + +void +Device::txDmaCopy() +{ + assert(txState == txCopy); + txState = txCopyDone; + physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen); + DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", + txDmaAddr, txDmaLen); + DDUMP(EthernetDMA, txDmaData, txDmaLen); +} + +void +Device::txDmaDone() +{ + txDmaCopy(); + txKick(); +} + +void +Device::transmit() +{ + if (txFifo.empty()) { + DPRINTF(Ethernet, "nothing to transmit\n"); + return; + } + + PacketPtr packet = txFifo.front(); + if (!interface->sendPacket(packet)) { + DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n", + txFifo.avail()); + goto reschedule; + } + + txFifo.pop(); + +#if TRACING_ON + if (DTRACE(Ethernet)) { + IpPtr ip(packet); + if (ip) { + DPRINTF(Ethernet, "ID is %d\n", ip->id()); + TcpPtr tcp(ip); + if (tcp) { + DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n", + tcp->sport(), tcp->dport()); + } + } + } +#endif + + DDUMP(Ethernet, packet->data, packet->length); + txBytes += packet->length; + txPackets++; + + DPRINTF(Ethernet, "Packet Transmit: successful txFifo Available %d\n", + txFifo.avail()); + + if (txFifo.size() <= params()->tx_fifo_threshold) + devIntrPost(Regs::Intr_TxFifo); + + devIntrPost(Regs::Intr_TxDone); + + reschedule: + if (!txFifo.empty() && !txEvent.scheduled()) { + DPRINTF(Ethernet, "reschedule transmit\n"); + txEvent.schedule(curTick + 1000); + } +} + +void +Device::txKick() +{ + DPRINTF(EthernetSM, "transmit kick txState=%s (txFifo.size=%d)\n", + TxStateStrings[txState], txFifo.size()); + + if (txKickTick > curTick) { + DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", + txKickTick); + return; + } + + next: + switch (txState) { + case txIdle: + if (txPioRequest) { + pioInterface->respond(txPioRequest, curTick + pioLatency); + txPioRequest = 0; + } + goto exit; + + case txFifoBlock: + if (!txPacket) { + // Grab a new packet from the fifo. + txPacket = new PacketData(16384); + txPacketBufPtr = txPacket->data; + } + + if (txFifo.avail() - txPacket->length < + Regs::get_TxData_Len(regs.TxData)) { + DPRINTF(EthernetSM, "transmit fifo full. Nothing to do.\n"); + goto exit; + } + + txState = txBeginCopy; + break; + + case txBeginCopy: + txDmaAddr = plat->pciToDma(Regs::get_TxData_Addr(regs.TxData)); + txDmaLen = Regs::get_TxData_Len(regs.TxData); + txDmaData = txPacketBufPtr; + + if (dmaInterface) { + if (!dmaInterface->busy()) { + dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, + curTick, &txDmaEvent, true); + txState = txCopy; + } + + goto exit; + } + + txState = txCopy; + if (dmaReadDelay != 0 || dmaReadFactor != 0) { + Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; + Tick start = curTick + dmaReadDelay + factor; + txDmaEvent.schedule(start); + goto exit; + } + + txDmaCopy(); + break; + + case txCopy: + DPRINTF(EthernetSM, "transmit machine still copying\n"); + goto exit; + + case txCopyDone: + txPacket->length += txDmaLen; + if ((regs.TxData & Regs::TxData_More)) { + txPacketBufPtr += txDmaLen; + } else { + assert(txPacket->length <= txFifo.avail()); + if ((regs.TxData & Regs::TxData_Checksum)) { + IpPtr ip(txPacket); + if (ip) { + TcpPtr tcp(ip); + if (tcp) { + tcp->sum(0); + tcp->sum(cksum(tcp)); + txTcpChecksums++; + } + + UdpPtr udp(ip); + if (udp) { + udp->sum(0); + udp->sum(cksum(udp)); + txUdpChecksums++; + } + + ip->sum(0); + ip->sum(cksum(ip)); + txIpChecksums++; + } + } + txFifo.push(txPacket); + txPacket = 0; + transmit(); + } + + regs.TxDone = txDmaLen | Regs::TxDone_Complete; + devIntrPost(Regs::Intr_TxData); + txState = txIdle; + break; + + default: + panic("Invalid txState!"); + } + + DPRINTF(EthernetSM, "entering next txState=%s\n", + TxStateStrings[txState]); + + goto next; + + exit: + /** + * @todo do we want to schedule a future kick? + */ + DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", + TxStateStrings[txState]); +} + +void +Device::transferDone() +{ + if (txFifo.empty()) { + DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); + return; + } + + DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); + + if (txEvent.scheduled()) + txEvent.reschedule(curTick + 1); + else + txEvent.schedule(curTick + 1); +} + +bool +Device::rxFilter(const PacketPtr &packet) +{ + if (!Regs::get_Config_Filter(regs.Config)) + return false; + + panic("receive filter not implemented\n"); + bool drop = true; + +#if 0 + string type; + + EthHdr *eth = packet->eth(); + if (eth->unicast()) { + // If we're accepting all unicast addresses + if (acceptUnicast) + drop = false; + + // If we make a perfect match + if (acceptPerfect && params->eaddr == eth.dst()) + drop = false; + + if (acceptArp && eth->type() == ETH_TYPE_ARP) + drop = false; + + } else if (eth->broadcast()) { + // if we're accepting broadcasts + if (acceptBroadcast) + drop = false; + + } else if (eth->multicast()) { + // if we're accepting all multicasts + if (acceptMulticast) + drop = false; + + } + + if (drop) { + DPRINTF(Ethernet, "rxFilter drop\n"); + DDUMP(EthernetData, packet->data, packet->length); + } +#endif + return drop; +} + +bool +Device::recvPacket(PacketPtr packet) +{ + rxBytes += packet->length; + rxPackets++; + + DPRINTF(Ethernet, "Receiving packet from wire, rxFifo Available is %d\n", + rxFifo.avail()); + + if (!rxEnable) { + DPRINTF(Ethernet, "receive disabled...packet dropped\n"); + interface->recvDone(); + return true; + } + + if (rxFilter(packet)) { + DPRINTF(Ethernet, "packet filtered...dropped\n"); + interface->recvDone(); + return true; + } + + if (rxFifo.size() >= params()->rx_fifo_threshold) + devIntrPost(Regs::Intr_RxFifo); + + if (!rxFifo.push(packet)) { + DPRINTF(Ethernet, + "packet will not fit in receive buffer...packet dropped\n"); + return false; + } + + interface->recvDone(); + devIntrPost(Regs::Intr_RxDone); + rxKick(); + return true; +} + +//===================================================================== +// +// +void +Base::serialize(ostream &os) +{ + // Serialize the PciDev base class + PciDev::serialize(os); + + SERIALIZE_SCALAR(rxEnable); + SERIALIZE_SCALAR(txEnable); + SERIALIZE_SCALAR(cpuIntrEnable); + + /* + * Keep track of pending interrupt status. + */ + SERIALIZE_SCALAR(intrTick); + SERIALIZE_SCALAR(cpuPendingIntr); + Tick intrEventTick = 0; + if (intrEvent) + intrEventTick = intrEvent->when(); + SERIALIZE_SCALAR(intrEventTick); +} + +void +Base::unserialize(Checkpoint *cp, const std::string §ion) +{ + // Unserialize the PciDev base class + PciDev::unserialize(cp, section); + + UNSERIALIZE_SCALAR(rxEnable); + UNSERIALIZE_SCALAR(txEnable); + UNSERIALIZE_SCALAR(cpuIntrEnable); + + /* + * Keep track of pending interrupt status. + */ + UNSERIALIZE_SCALAR(intrTick); + UNSERIALIZE_SCALAR(cpuPendingIntr); + Tick intrEventTick; + UNSERIALIZE_SCALAR(intrEventTick); + if (intrEventTick) { + intrEvent = new IntrEvent(this, true); + intrEvent->schedule(intrEventTick); + } +} + +void +Device::serialize(ostream &os) +{ + // Serialize the PciDev base class + Base::serialize(os); + + if (rxDmaEvent.scheduled()) + rxDmaCopy(); + + if (txDmaEvent.scheduled()) + txDmaCopy(); + + /* + * Serialize the device registers + */ + SERIALIZE_SCALAR(regs.Config); + SERIALIZE_SCALAR(regs.RxMaxCopy); + SERIALIZE_SCALAR(regs.TxMaxCopy); + SERIALIZE_SCALAR(regs.RxThreshold); + SERIALIZE_SCALAR(regs.TxThreshold); + SERIALIZE_SCALAR(regs.IntrStatus); + SERIALIZE_SCALAR(regs.IntrMask); + SERIALIZE_SCALAR(regs.RxData); + SERIALIZE_SCALAR(regs.RxDone); + SERIALIZE_SCALAR(regs.TxData); + SERIALIZE_SCALAR(regs.TxDone); + + /* + * Serialize rx state machine + */ + int rxState = this->rxState; + SERIALIZE_SCALAR(rxState); + rxFifo.serialize("rxFifo", os); + bool rxPacketExists = rxPacket; + SERIALIZE_SCALAR(rxPacketExists); + if (rxPacketExists) { + rxPacket->serialize("rxPacket", os); + uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); + SERIALIZE_SCALAR(rxPktBufPtr); + SERIALIZE_SCALAR(rxPktBytes); + } + SERIALIZE_SCALAR(rxDoneData); + + /* + * Serialize tx state machine + */ + int txState = this->txState; + SERIALIZE_SCALAR(txState); + txFifo.serialize("txFifo", os); + bool txPacketExists = txPacket; + SERIALIZE_SCALAR(txPacketExists); + if (txPacketExists) { + txPacket->serialize("txPacket", os); + uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); + SERIALIZE_SCALAR(txPktBufPtr); + SERIALIZE_SCALAR(txPktBytes); + } + + /* + * If there's a pending transmit, store the time so we can + * reschedule it later + */ + Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0; + SERIALIZE_SCALAR(transmitTick); +} + +void +Device::unserialize(Checkpoint *cp, const std::string §ion) +{ + // Unserialize the PciDev base class + Base::unserialize(cp, section); + + /* + * Unserialize the device registers + */ + UNSERIALIZE_SCALAR(regs.Config); + UNSERIALIZE_SCALAR(regs.RxMaxCopy); + UNSERIALIZE_SCALAR(regs.TxMaxCopy); + UNSERIALIZE_SCALAR(regs.RxThreshold); + UNSERIALIZE_SCALAR(regs.TxThreshold); + UNSERIALIZE_SCALAR(regs.IntrStatus); + UNSERIALIZE_SCALAR(regs.IntrMask); + UNSERIALIZE_SCALAR(regs.RxData); + UNSERIALIZE_SCALAR(regs.RxDone); + UNSERIALIZE_SCALAR(regs.TxData); + UNSERIALIZE_SCALAR(regs.TxDone); + + /* + * Unserialize rx state machine + */ + int rxState; + UNSERIALIZE_SCALAR(rxState); + this->rxState = (RxState) rxState; + rxFifo.unserialize("rxFifo", cp, section); + bool rxPacketExists; + UNSERIALIZE_SCALAR(rxPacketExists); + rxPacket = 0; + if (rxPacketExists) { + rxPacket = new PacketData; + rxPacket->unserialize("rxPacket", cp, section); + uint32_t rxPktBufPtr; + UNSERIALIZE_SCALAR(rxPktBufPtr); + this->rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; + UNSERIALIZE_SCALAR(rxPktBytes); + } + UNSERIALIZE_SCALAR(rxDoneData); + + /* + * Unserialize tx state machine + */ + int txState; + UNSERIALIZE_SCALAR(txState); + this->txState = (TxState) txState; + txFifo.unserialize("txFifo", cp, section); + bool txPacketExists; + UNSERIALIZE_SCALAR(txPacketExists); + txPacket = 0; + if (txPacketExists) { + txPacket = new PacketData; + txPacket->unserialize("txPacket", cp, section); + uint32_t txPktBufPtr; + UNSERIALIZE_SCALAR(txPktBufPtr); + this->txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; + UNSERIALIZE_SCALAR(txPktBytes); + } + + /* + * If there's a pending transmit, reschedule it now + */ + Tick transmitTick; + UNSERIALIZE_SCALAR(transmitTick); + if (transmitTick) + txEvent.schedule(curTick + transmitTick); + + /* + * re-add addrRanges to bus bridges + */ + if (pioInterface) { + pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); + pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1])); + } +} + +Tick +Device::cacheAccess(MemReqPtr &req) +{ + //The mask is to give you only the offset into the device register file + Addr daddr = req->paddr - addr; + + DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n", + req->paddr, daddr); + + Tick when = curTick + pioLatency; + + switch (daddr) { + case Regs::RxDone: + if (rxState != rxIdle) { + rxPioRequest = req; + when = 0; + } + break; + + case Regs::TxDone: + if (txState != txIdle) { + txPioRequest = req; + when = 0; + } + break; + } + + return when; +} + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface) + + SimObjectParam<EtherInt *> peer; + SimObjectParam<Device *> device; + +END_DECLARE_SIM_OBJECT_PARAMS(Interface) + +BEGIN_INIT_SIM_OBJECT_PARAMS(Interface) + + INIT_PARAM_DFLT(peer, "peer interface", NULL), + INIT_PARAM(device, "Ethernet device of this interface") + +END_INIT_SIM_OBJECT_PARAMS(Interface) + +CREATE_SIM_OBJECT(Interface) +{ + Interface *dev_int = new Interface(getInstanceName(), device); + + EtherInt *p = (EtherInt *)peer; + if (p) { + dev_int->setPeer(p); + p->setPeer(dev_int); + } + + return dev_int; +} + +REGISTER_SIM_OBJECT("SinicInt", Interface) + + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device) + + Param<Tick> tx_delay; + Param<Tick> rx_delay; + Param<Tick> intr_delay; + SimObjectParam<MemoryController *> mmu; + SimObjectParam<PhysicalMemory *> physmem; + Param<bool> rx_filter; + Param<string> hardware_address; + SimObjectParam<Bus*> header_bus; + SimObjectParam<Bus*> payload_bus; + SimObjectParam<HierParams *> hier; + Param<Tick> pio_latency; + SimObjectParam<PciConfigAll *> configspace; + SimObjectParam<PciConfigData *> configdata; + SimObjectParam<Platform *> platform; + Param<uint32_t> pci_bus; + Param<uint32_t> pci_dev; + Param<uint32_t> pci_func; + Param<uint32_t> rx_max_copy; + Param<uint32_t> tx_max_copy; + Param<uint32_t> rx_fifo_size; + Param<uint32_t> tx_fifo_size; + Param<uint32_t> rx_fifo_threshold; + Param<uint32_t> tx_fifo_threshold; + Param<Tick> dma_read_delay; + Param<Tick> dma_read_factor; + Param<Tick> dma_write_delay; + Param<Tick> dma_write_factor; + +END_DECLARE_SIM_OBJECT_PARAMS(Device) + +BEGIN_INIT_SIM_OBJECT_PARAMS(Device) + + INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000), + INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000), + INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0), + INIT_PARAM(mmu, "Memory Controller"), + INIT_PARAM(physmem, "Physical Memory"), + INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true), + INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address", + "00:99:00:00:00:01"), + INIT_PARAM_DFLT(header_bus, "The IO Bus to attach to for headers", NULL), + INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL), + INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), + INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), + INIT_PARAM(configspace, "PCI Configspace"), + INIT_PARAM(configdata, "PCI Config data"), + INIT_PARAM(platform, "Platform"), + INIT_PARAM(pci_bus, "PCI bus"), + INIT_PARAM(pci_dev, "PCI device number"), + INIT_PARAM(pci_func, "PCI function code"), + INIT_PARAM_DFLT(rx_max_copy, "rx max copy", 16*1024), + INIT_PARAM_DFLT(tx_max_copy, "rx max copy", 16*1024), + INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 64*1024), + INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 64*1024), + INIT_PARAM_DFLT(rx_fifo_threshold, "max size in bytes of rxFifo", 48*1024), + INIT_PARAM_DFLT(tx_fifo_threshold, "max size in bytes of txFifo", 16*1024), + INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0), + INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0), + INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0), + INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0) + +END_INIT_SIM_OBJECT_PARAMS(Device) + + +CREATE_SIM_OBJECT(Device) +{ + Device::Params *params = new Device::Params; + params->name = getInstanceName(); + params->intr_delay = intr_delay; + params->physmem = physmem; + params->tx_delay = tx_delay; + params->rx_delay = rx_delay; + params->mmu = mmu; + params->hier = hier; + params->header_bus = header_bus; + params->payload_bus = payload_bus; + params->pio_latency = pio_latency; + params->configSpace = configspace; + params->configData = configdata; + params->plat = platform; + params->busNum = pci_bus; + params->deviceNum = pci_dev; + params->functionNum = pci_func; + params->rx_filter = rx_filter; + params->eaddr = hardware_address; + params->rx_max_copy = rx_max_copy; + params->tx_max_copy = tx_max_copy; + params->rx_fifo_size = rx_fifo_size; + params->tx_fifo_size = tx_fifo_size; + params->rx_fifo_threshold = rx_fifo_threshold; + params->tx_fifo_threshold = tx_fifo_threshold; + params->dma_read_delay = dma_read_delay; + params->dma_read_factor = dma_read_factor; + params->dma_write_delay = dma_write_delay; + params->dma_write_factor = dma_write_factor; + return new Device(params); +} + +REGISTER_SIM_OBJECT("Sinic", Device) + +/* namespace Sinic */ } diff --git a/dev/sinic.hh b/dev/sinic.hh new file mode 100644 index 000000000..ef515ffad --- /dev/null +++ b/dev/sinic.hh @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __DEV_SINIC_HH__ +#define __DEV_SINIC_HH__ + +#include "base/inet.hh" +#include "base/statistics.hh" +#include "dev/etherint.hh" +#include "dev/etherpkt.hh" +#include "dev/io_device.hh" +#include "dev/pcidev.hh" +#include "dev/pktfifo.hh" +#include "dev/sinicreg.hh" +#include "mem/bus/bus.hh" +#include "sim/eventq.hh" + +namespace Sinic { + +class Interface; +class Base : public PciDev +{ + protected: + bool rxEnable; + bool txEnable; + + protected: + Tick intrDelay; + Tick intrTick; + bool cpuIntrEnable; + bool cpuPendingIntr; + void cpuIntrPost(Tick when); + void cpuInterrupt(); + void cpuIntrClear(); + + typedef EventWrapper<Base, &Base::cpuInterrupt> IntrEvent; + friend class IntrEvent; + IntrEvent *intrEvent; + Interface *interface; + + bool cpuIntrPending() const; + void cpuIntrAck() { cpuIntrClear(); } + +/** + * Serialization stuff + */ + public: + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); + +/** + * Construction/Destruction/Parameters + */ + public: + struct Params : public PciDev::Params + { + Tick intr_delay; + }; + + Base(Params *p); +}; + +class Device : public Base +{ + protected: + Platform *plat; + PhysicalMemory *physmem; + + protected: + /** Receive State Machine States */ + enum RxState { + rxIdle, + rxFifoBlock, + rxBeginCopy, + rxCopy, + rxCopyDone + }; + + /** Transmit State Machine states */ + enum TxState { + txIdle, + txFifoBlock, + txBeginCopy, + txCopy, + txCopyDone + }; + + /** device register file */ + struct { + uint32_t Config; + uint32_t RxMaxCopy; + uint32_t TxMaxCopy; + uint32_t RxThreshold; + uint32_t TxThreshold; + uint32_t IntrStatus; + uint32_t IntrMask; + uint64_t RxData; + uint64_t RxDone; + uint64_t TxData; + uint64_t TxDone; + } regs; + + private: + Addr addr; + static const Addr size = Regs::Size; + + protected: + RxState rxState; + PacketFifo rxFifo; + PacketPtr rxPacket; + uint8_t *rxPacketBufPtr; + int rxPktBytes; + uint64_t rxDoneData; + Addr rxDmaAddr; + uint8_t *rxDmaData; + int rxDmaLen; + + TxState txState; + PacketFifo txFifo; + PacketPtr txPacket; + uint8_t *txPacketBufPtr; + int txPktBytes; + Addr txDmaAddr; + uint8_t *txDmaData; + int txDmaLen; + + protected: + void reset(); + + void rxKick(); + Tick rxKickTick; + typedef EventWrapper<Device, &Device::rxKick> RxKickEvent; + friend class RxKickEvent; + + void txKick(); + Tick txKickTick; + typedef EventWrapper<Device, &Device::txKick> TxKickEvent; + friend class TxKickEvent; + + /** + * Retransmit event + */ + void transmit(); + void txEventTransmit() + { + transmit(); + if (txState == txFifoBlock) + txKick(); + } + typedef EventWrapper<Device, &Device::txEventTransmit> TxEvent; + friend class TxEvent; + TxEvent txEvent; + + void txDump() const; + void rxDump() const; + + /** + * receive address filter + */ + bool rxFilter(const PacketPtr &packet); + +/** + * device configuration + */ + void changeConfig(uint32_t newconfig); + +/** + * device ethernet interface + */ + public: + bool recvPacket(PacketPtr packet); + void transferDone(); + void setInterface(Interface *i) { assert(!interface); interface = i; } + +/** + * DMA parameters + */ + protected: + void rxDmaCopy(); + void rxDmaDone(); + friend class EventWrapper<Device, &Device::rxDmaDone>; + EventWrapper<Device, &Device::rxDmaDone> rxDmaEvent; + + void txDmaCopy(); + void txDmaDone(); + friend class EventWrapper<Device, &Device::txDmaDone>; + EventWrapper<Device, &Device::rxDmaDone> txDmaEvent; + + Tick dmaReadDelay; + Tick dmaReadFactor; + Tick dmaWriteDelay; + Tick dmaWriteFactor; + +/** + * PIO parameters + */ + protected: + MemReqPtr rxPioRequest; + MemReqPtr txPioRequest; + +/** + * Interrupt management + */ + protected: + void devIntrPost(uint32_t interrupts); + void devIntrClear(uint32_t interrupts = Regs::Intr_All); + void devIntrChangeMask(uint32_t newmask); + +/** + * PCI Configuration interface + */ + public: + virtual void WriteConfig(int offset, int size, uint32_t data); + +/** + * Memory Interface + */ + public: + virtual Fault read(MemReqPtr &req, uint8_t *data); + virtual Fault write(MemReqPtr &req, const uint8_t *data); + Tick cacheAccess(MemReqPtr &req); + +/** + * Statistics + */ + private: + Stats::Scalar<> rxBytes; + Stats::Formula rxBandwidth; + Stats::Scalar<> rxPackets; + Stats::Formula rxPacketRate; + Stats::Scalar<> rxIpPackets; + Stats::Scalar<> rxTcpPackets; + Stats::Scalar<> rxUdpPackets; + Stats::Scalar<> rxIpChecksums; + Stats::Scalar<> rxTcpChecksums; + Stats::Scalar<> rxUdpChecksums; + + Stats::Scalar<> txBytes; + Stats::Formula txBandwidth; + Stats::Scalar<> txPackets; + Stats::Formula txPacketRate; + Stats::Scalar<> txIpPackets; + Stats::Scalar<> txTcpPackets; + Stats::Scalar<> txUdpPackets; + Stats::Scalar<> txIpChecksums; + Stats::Scalar<> txTcpChecksums; + Stats::Scalar<> txUdpChecksums; + + public: + virtual void regStats(); + +/** + * Serialization stuff + */ + public: + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); + +/** + * Construction/Destruction/Parameters + */ + public: + struct Params : public Base::Params + { + IntrControl *i; + PhysicalMemory *pmem; + Tick tx_delay; + Tick rx_delay; + HierParams *hier; + Bus *header_bus; + Bus *payload_bus; + Tick pio_latency; + PhysicalMemory *physmem; + IntrControl *intctrl; + bool rx_filter; + Net::EthAddr eaddr; + uint32_t rx_max_copy; + uint32_t tx_max_copy; + uint32_t rx_fifo_size; + uint32_t tx_fifo_size; + uint32_t rx_fifo_threshold; + uint32_t tx_fifo_threshold; + Tick dma_read_delay; + Tick dma_read_factor; + Tick dma_write_delay; + Tick dma_write_factor; + }; + + protected: + const Params *params() const { return (const Params *)_params; } + + public: + Device(Params *params); + ~Device(); +}; + +/* + * Ethernet Interface for an Ethernet Device + */ +class Interface : public EtherInt +{ + private: + Device *dev; + + public: + Interface(const std::string &name, Device *d) + : EtherInt(name), dev(d) { dev->setInterface(this); } + + virtual bool recvPacket(PacketPtr pkt) { return dev->recvPacket(pkt); } + virtual void sendDone() { dev->transferDone(); } +}; + +/* namespace Sinic */ } + +#endif // __DEV_SINIC_HH__ diff --git a/dev/sinicreg.hh b/dev/sinicreg.hh new file mode 100644 index 000000000..9f3412a31 --- /dev/null +++ b/dev/sinicreg.hh @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __DEV_SINICREG_HH__ +#define __DEV_SINICREG_HH__ + +#define __SINIC_REG32(NAME, VAL) static const uint32_t NAME = (VAL) +#define __SINIC_REG64(NAME, VAL) static const uint64_t NAME = (VAL) + +#define __SINIC_VAL32(NAME, OFFSET, WIDTH) \ + static const uint32_t NAME##_width = WIDTH; \ + static const uint32_t NAME##_offset = OFFSET; \ + static const uint32_t NAME##_mask = (1 << WIDTH) - 1; \ + static const uint32_t NAME = ((1 << WIDTH) - 1) << OFFSET; \ + static inline uint32_t get_##NAME(uint32_t reg) \ + { return (reg & NAME) >> OFFSET; } \ + static inline uint32_t set_##NAME(uint32_t reg, uint32_t val) \ + { return (reg & ~NAME) | ((val << OFFSET) & NAME); } + +#define __SINIC_VAL64(NAME, OFFSET, WIDTH) \ + static const uint64_t NAME##_width = WIDTH; \ + static const uint64_t NAME##_offset = OFFSET; \ + static const uint64_t NAME##_mask = (ULL(1) << WIDTH) - 1; \ + static const uint64_t NAME = ((ULL(1) << WIDTH) - 1) << OFFSET; \ + static inline uint64_t get_##NAME(uint64_t reg) \ + { return (reg & NAME) >> OFFSET; } \ + static inline uint64_t set_##NAME(uint64_t reg, uint64_t val) \ + { return (reg & ~NAME) | ((val << OFFSET) & NAME); } + +namespace Sinic { +namespace Regs { + +// Registers +__SINIC_REG32(Config, 0x00); // 32: configuration register +__SINIC_REG32(RxMaxCopy, 0x04); // 32: max rx copy +__SINIC_REG32(TxMaxCopy, 0x08); // 32: max tx copy +__SINIC_REG32(RxThreshold, 0x0c); // 32: receive fifo threshold +__SINIC_REG32(TxThreshold, 0x10); // 32: transmit fifo threshold +__SINIC_REG32(IntrStatus, 0x14); // 32: interrupt status +__SINIC_REG32(IntrMask, 0x18); // 32: interrupt mask +__SINIC_REG32(RxData, 0x20); // 64: receive data +__SINIC_REG32(RxDone, 0x28); // 64: receive done +__SINIC_REG32(RxWait, 0x30); // 64: receive done (busy wait) +__SINIC_REG32(TxData, 0x38); // 64: transmit data +__SINIC_REG32(TxDone, 0x40); // 64: transmit done +__SINIC_REG32(TxWait, 0x48); // 64: transmit done (busy wait) +__SINIC_REG32(HwAddr, 0x50); // 64: mac address +__SINIC_REG32(Size, 0x58); + +// Config register bits +__SINIC_VAL32(Config_Reset, 31, 1); // reset chip +__SINIC_VAL32(Config_Filter, 7, 1); // enable receive filter +__SINIC_VAL32(Config_Vlan, 6, 1); // enable vlan tagging +__SINIC_VAL32(Config_Virtual, 5, 1); // enable virtual addressing +__SINIC_VAL32(Config_Desc, 4, 1); // enable tx/rx descriptors +__SINIC_VAL32(Config_Poll, 3, 1); // enable polling +__SINIC_VAL32(Config_IntEn, 2, 1); // enable interrupts +__SINIC_VAL32(Config_TxEn, 1, 1); // enable transmit +__SINIC_VAL32(Config_RxEn, 0, 1); // enable receive + +// Interrupt register bits +__SINIC_VAL32(Intr_TxFifo, 5, 1); // Fifo oflow/uflow/threshold +__SINIC_VAL32(Intr_TxData, 4, 1); // DMA Completed w/ interrupt +__SINIC_VAL32(Intr_TxDone, 3, 1); // Packet transmitted +__SINIC_VAL32(Intr_RxFifo, 2, 1); // Fifo oflow/uflow/threshold +__SINIC_VAL32(Intr_RxData, 1, 1); // DMA Completed w/ interrupt +__SINIC_VAL32(Intr_RxDone, 0, 1); // Packet received +__SINIC_REG32(Intr_All, 0x3f); +__SINIC_REG32(Intr_NoDelay, 0x24); +__SINIC_REG32(Intr_Res, ~0x3f); + +// RX Data Description +__SINIC_VAL64(RxData_Len, 40, 20); // 0 - 1M +__SINIC_VAL64(RxData_Addr, 0, 40); // Address 1TB + +// TX Data Description +__SINIC_VAL64(TxData_More, 63, 1); +__SINIC_VAL64(TxData_Checksum, 62, 1); +__SINIC_VAL64(TxData_Len, 40, 20); // 0 - 1M +__SINIC_VAL64(TxData_Addr, 0, 40); // Address 1TB + +// RX Done/Busy Information +__SINIC_VAL64(RxDone_Complete, 63, 1); +__SINIC_VAL64(RxDone_IpPacket, 45, 1); +__SINIC_VAL64(RxDone_TcpPacket, 44, 1); +__SINIC_VAL64(RxDone_UdpPacket, 43, 1); +__SINIC_VAL64(RxDone_IpError, 42, 1); +__SINIC_VAL64(RxDone_TcpError, 41, 1); +__SINIC_VAL64(RxDone_UdpError, 40, 1); +__SINIC_VAL64(RxDone_More, 32, 1); +__SINIC_VAL64(RxDone_FifoLen, 20, 8); // up to 255 packets +__SINIC_VAL64(RxDone_CopyLen, 0, 20); // up to 256k + +// TX Done/Busy Information +__SINIC_VAL64(TxDone_Complete, 63, 1); +__SINIC_VAL64(TxDone_FifoLen, 20, 8); // up to 255 packets +__SINIC_VAL64(TxDone_CopyLen, 0, 20); // up to 256k + +inline int +regSize(int offset) +{ + static const char sizes[] = { + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 0, + 8, 0, + 8, 0, + 8, 0, + 8, 0, + 8, 0, + 8, 0, + 8, 0 + }; + + if (offset & 0x3) + return 0; + + if (offset >= Size) + return 0; + + return sizes[offset / 4]; +} + +inline const char * +regName(int offset) +{ + static const char *names[] = { + "Config", + "RxMaxCopy", + "TxMaxCopy", + "RxThreshold", + "TxThreshold", + "IntrStatus", + "IntrMask", + "invalid", + "RxData", "invalid", + "RxDone", "invalid", + "RxWait", "invalid", + "TxData", "invalid", + "TxDone", "invalid", + "TxWait", "invalid", + "HwAddr", "invalid" + }; + + if (offset & 0x3) + return "invalid"; + + if (offset >= Size) + return "invalid"; + + return names[offset / 4]; +} + +/* namespace Regs */ } +/* namespace Sinic */ } + +#endif // __DEV_SINICREG_HH__ diff --git a/dev/tsunami.cc b/dev/tsunami.cc index ce2d473a9..f98254354 100644 --- a/dev/tsunami.cc +++ b/dev/tsunami.cc @@ -77,13 +77,19 @@ Tsunami::clearConsoleInt() void Tsunami::postPciInt(int line) { - this->cchip->postDRIR(line); + cchip->postDRIR(line); } void Tsunami::clearPciInt(int line) { - this->cchip->clearDRIR(line); + cchip->clearDRIR(line); +} + +Addr +Tsunami::pciToDma(Addr pciAddr) const +{ + return pchip->translatePciToDma(pciAddr); } void diff --git a/dev/tsunami.hh b/dev/tsunami.hh index 0a7fdbcd9..05563f80b 100644 --- a/dev/tsunami.hh +++ b/dev/tsunami.hh @@ -118,6 +118,8 @@ class Tsunami : public Platform */ virtual void clearPciInt(int line); + virtual Addr pciToDma(Addr pciAddr) const; + /** * Serialize this object to the given output stream. * @param os The stream to serialize to. diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc index 20b39f21f..c389063d0 100644 --- a/dev/tsunami_cchip.cc +++ b/dev/tsunami_cchip.cc @@ -83,7 +83,7 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data) DPRINTF(Tsunami, "read va=%#x size=%d\n", req->vaddr, req->size); - Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; + Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6; ExecContext *xc = req->xc; switch (req->size) { @@ -169,7 +169,7 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) DPRINTF(Tsunami, "write - va=%#x value=%#x size=%d \n", req->vaddr, *(uint64_t*)data, req->size); - Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; + Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6; bool supportedWrite = false; uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size(); diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc index fab1b4b38..51ff8b81c 100644 --- a/dev/tsunami_io.cc +++ b/dev/tsunami_io.cc @@ -196,7 +196,7 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data) DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", req->vaddr, req->size, req->vaddr & 0xfff); - Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)); + Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); switch(req->size) { @@ -298,7 +298,7 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data) DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n", req->vaddr, req->size, req->vaddr & 0xfff, dt64); - Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)); + Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); switch(req->size) { case sizeof(uint8_t): diff --git a/dev/tsunami_pchip.cc b/dev/tsunami_pchip.cc index 4c94d12af..9af19d930 100644 --- a/dev/tsunami_pchip.cc +++ b/dev/tsunami_pchip.cc @@ -82,7 +82,7 @@ TsunamiPChip::read(MemReqPtr &req, uint8_t *data) DPRINTF(Tsunami, "read va=%#x size=%d\n", req->vaddr, req->size); - Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; + Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6; switch (req->size) { @@ -171,7 +171,7 @@ TsunamiPChip::write(MemReqPtr &req, const uint8_t *data) DPRINTF(Tsunami, "write - va=%#x size=%d \n", req->vaddr, req->size); - Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; + Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6; switch (req->size) { diff --git a/dev/uart.cc b/dev/uart.cc index b71ab2d44..2ff94dda5 100644 --- a/dev/uart.cc +++ b/dev/uart.cc @@ -44,7 +44,6 @@ #include "mem/bus/pio_interface_impl.hh" #include "mem/functional_mem/memory_control.hh" #include "sim/builder.hh" -#include "targetarch/ev5.hh" using namespace std; @@ -118,7 +117,7 @@ Uart::Uart(const string &name, SimConsole *c, MemoryController *mmu, Addr a, Fault Uart::read(MemReqPtr &req, uint8_t *data) { - Addr daddr = req->paddr - (addr & PA_IMPL_MASK); + Addr daddr = req->paddr - (addr & EV5::PAddrImplMask); DPRINTF(Uart, " read register %#x\n", daddr); @@ -246,7 +245,7 @@ Uart::read(MemReqPtr &req, uint8_t *data) Fault Uart::write(MemReqPtr &req, const uint8_t *data) { - Addr daddr = req->paddr - (addr & PA_IMPL_MASK); + Addr daddr = req->paddr - (addr & EV5::PAddrImplMask); DPRINTF(Uart, " write register %#x value %#x\n", daddr, *(uint8_t*)data); diff --git a/kern/tru64/tru64_events.cc b/kern/tru64/tru64_events.cc index a322060d8..f4300116e 100644 --- a/kern/tru64/tru64_events.cc +++ b/kern/tru64/tru64_events.cc @@ -48,7 +48,7 @@ BadAddrEvent::process(ExecContext *xc) uint64_t a0 = xc->regs.intRegFile[ArgumentReg0]; if (!TheISA::IsK0Seg(a0) || - xc->memctrl->badaddr(TheISA::K0Seg2Phys(a0) & PA_IMPL_MASK)) { + xc->memctrl->badaddr(TheISA::K0Seg2Phys(a0) & EV5::PAddrImplMask)) { DPRINTF(BADADDR, "badaddr arg=%#x bad\n", a0); xc->regs.intRegFile[ReturnValueReg] = 0x1; |