diff options
-rw-r--r-- | configs/example/fs.py | 198 | ||||
-rw-r--r-- | configs/example/se.py | 171 | ||||
-rw-r--r-- | src/base/traceflags.py | 1 | ||||
-rw-r--r-- | src/cpu/simple/atomic.cc | 11 | ||||
-rw-r--r-- | src/dev/i8254xGBe.cc | 156 | ||||
-rw-r--r-- | src/dev/i8254xGBe.hh | 7 | ||||
-rw-r--r-- | src/dev/i8254xGBe_defs.hh | 235 | ||||
-rw-r--r-- | src/mem/cache/base_cache.cc | 4 | ||||
-rw-r--r-- | src/mem/cache/cache_impl.hh | 64 | ||||
-rw-r--r-- | src/mem/cache/miss/blocking_buffer.hh | 18 | ||||
-rw-r--r-- | src/mem/cache/miss/miss_queue.hh | 22 | ||||
-rw-r--r-- | src/mem/cache/miss/mshr.hh | 20 | ||||
-rw-r--r-- | src/mem/cache/miss/mshr_queue.hh | 26 | ||||
-rw-r--r-- | src/mem/cache/tags/split.hh | 8 | ||||
-rw-r--r-- | src/mem/cache/tags/split_blk.hh | 2 | ||||
-rw-r--r-- | src/mem/packet.cc | 4 | ||||
-rw-r--r-- | src/mem/tport.cc | 64 | ||||
-rw-r--r-- | src/mem/tport.hh | 33 | ||||
-rw-r--r-- | src/python/m5/__init__.py | 3 | ||||
-rw-r--r-- | src/python/m5/objects/Ethernet.py | 2 | ||||
-rw-r--r-- | src/sim/pseudo_inst.cc | 2 |
21 files changed, 838 insertions, 213 deletions
diff --git a/configs/example/fs.py b/configs/example/fs.py index a5b8772af..76b62a066 100644 --- a/configs/example/fs.py +++ b/configs/example/fs.py @@ -40,26 +40,49 @@ if not m5.build_env['FULL_SYSTEM']: parser = optparse.OptionParser() -parser.add_option("-d", "--detailed", action="store_true") -parser.add_option("-t", "--timing", action="store_true") -parser.add_option("-n", "--num_cpus", type="int", default=1) -parser.add_option("--caches", action="store_true") -parser.add_option("-m", "--maxtick", type="int") -parser.add_option("--maxtime", type="float") +# Benchmark options parser.add_option("--dual", action="store_true", help="Simulate two systems attached with an ethernet link") parser.add_option("-b", "--benchmark", action="store", type="string", dest="benchmark", help="Specify the benchmark to run. Available benchmarks: %s"\ % DefinedBenchmarks) + +# system options +parser.add_option("-d", "--detailed", action="store_true") +parser.add_option("-t", "--timing", action="store_true") +parser.add_option("-n", "--num_cpus", type="int", default=1) +parser.add_option("--caches", action="store_true") + +# Run duration options +parser.add_option("-m", "--maxtick", type="int") +parser.add_option("--maxtime", type="float") + +# Metafile options parser.add_option("--etherdump", action="store", type="string", dest="etherdump", help="Specify the filename to dump a pcap capture of the" \ "ethernet traffic") + +# Checkpointing options +###Note that performing checkpointing via python script files will override +###checkpoint instructions built into binaries. +parser.add_option("--take_checkpoints", action="store", type="string", + help="<M,N> will take checkpoint at cycle M and every N cycles \ + thereafter") +parser.add_option("--max_checkpoints", action="store", type="int", + help="the maximum number of checkpoints to drop", + default=5) parser.add_option("--checkpoint_dir", action="store", type="string", help="Place all checkpoints in this absolute directory") -parser.add_option("-c", "--checkpoint", action="store", type="int", +parser.add_option("-r", "--checkpoint_restore", action="store", type="int", help="restore from checkpoint <N>") +# CPU Switching - default switch model goes from a checkpoint +# to a timing simple CPU with caches to warm up, then to detailed CPU for +# data measurement +parser.add_option("-s", "--standard_switch", action="store_true", + help="switch from one cpu mode to another") + (options, args) = parser.parse_args() if args: @@ -74,23 +97,24 @@ class MyCache(BaseCache): tgts_per_mshr = 5 protocol = CoherenceProtocol(protocol='moesi') -# client system CPU is always simple... note this is an assignment of +# driver system CPU is always simple... note this is an assignment of # a class, not an instance. -ClientCPUClass = AtomicSimpleCPU -client_mem_mode = 'atomic' +DriveCPUClass = AtomicSimpleCPU +drive_mem_mode = 'atomic' +# system under test can be any of these CPUs if options.detailed: - ServerCPUClass = DerivO3CPU - server_mem_mode = 'timing' + TestCPUClass = DerivO3CPU + test_mem_mode = 'timing' elif options.timing: - ServerCPUClass = TimingSimpleCPU - server_mem_mode = 'timing' + TestCPUClass = TimingSimpleCPU + test_mem_mode = 'timing' else: - ServerCPUClass = AtomicSimpleCPU - server_mem_mode = 'atomic' + TestCPUClass = AtomicSimpleCPU + test_mem_mode = 'atomic' -ServerCPUClass.clock = '2GHz' -ClientCPUClass.clock = '2GHz' +TestCPUClass.clock = '2GHz' +DriveCPUClass.clock = '2GHz' if options.benchmark: try: @@ -105,38 +129,59 @@ else: else: bm = [SysConfig()] -server_sys = makeLinuxAlphaSystem(server_mem_mode, bm[0]) +test_sys = makeLinuxAlphaSystem(test_mem_mode, bm[0]) np = options.num_cpus -server_sys.cpu = [ServerCPUClass(cpu_id=i) for i in xrange(np)] +test_sys.cpu = [TestCPUClass(cpu_id=i) for i in xrange(np)] for i in xrange(np): - if options.caches: - server_sys.cpu[i].addPrivateSplitL1Caches(MyCache(size = '32kB'), + if options.caches and not options.standard_switch: + test_sys.cpu[i].addPrivateSplitL1Caches(MyCache(size = '32kB'), MyCache(size = '64kB')) - server_sys.cpu[i].connectMemPorts(server_sys.membus) - server_sys.cpu[i].mem = server_sys.physmem + test_sys.cpu[i].connectMemPorts(test_sys.membus) + test_sys.cpu[i].mem = test_sys.physmem if len(bm) == 2: - client_sys = makeLinuxAlphaSystem(client_mem_mode, bm[1]) - client_sys.cpu = ClientCPUClass(cpu_id=0) - client_sys.cpu.connectMemPorts(client_sys.membus) - client_sys.cpu.mem = client_sys.physmem - root = makeDualRoot(server_sys, client_sys, options.etherdump) + drive_sys = makeLinuxAlphaSystem(drive_mem_mode, bm[1]) + drive_sys.cpu = DriveCPUClass(cpu_id=0) + drive_sys.cpu.connectMemPorts(drive_sys.membus) + drive_sys.cpu.mem = drive_sys.physmem + root = makeDualRoot(test_sys, drive_sys, options.etherdump) elif len(bm) == 1: - root = Root(clock = '1THz', system = server_sys) + root = Root(clock = '1THz', system = test_sys) else: print "Error I don't know how to create more than 2 systems." sys.exit(1) +if options.standard_switch: + switch_cpus = [TimingSimpleCPU(defer_registration=True, cpu_id=(np+i)) for i in xrange(np)] + switch_cpus1 = [DerivO3CPU(defer_registration=True, cpu_id=(2*np+i)) for i in xrange(np)] + for i in xrange(np): + switch_cpus[i].system = test_sys + switch_cpus1[i].system = test_sys + switch_cpus[i].clock = TestCPUClass.clock + switch_cpus1[i].clock = TestCPUClass.clock + if options.caches: + switch_cpus[i].addPrivateSplitL1Caches(MyCache(size = '32kB'), + MyCache(size = '64kB')) + + switch_cpus[i].mem = test_sys.physmem + switch_cpus1[i].mem = test_sys.physmem + switch_cpus[i].connectMemPorts(test_sys.membus) + root.switch_cpus = switch_cpus + root.switch_cpus1 = switch_cpus1 + switch_cpu_list = [(test_sys.cpu[i], switch_cpus[i]) for i in xrange(np)] + switch_cpu_list1 = [(switch_cpus[i], switch_cpus1[i]) for i in xrange(np)] + m5.instantiate(root) -if options.checkpoint: +if options.checkpoint_dir: + cptdir = options.checkpoint_dir +else: + cptdir = os.getcwd() + +if options.checkpoint_restore: from os.path import isdir from os import listdir, getcwd import re - if options.checkpoint_dir: - cptdir = options.checkpoint_dir - else: - cptdir = getcwd() if not isdir(cptdir): m5.panic("checkpoint dir %s does not exist!" % cptdir) @@ -149,10 +194,26 @@ if options.checkpoint: if match: cpts.append(match.group(1)) - if options.checkpoint > len(cpts): - m5.panic('Checkpoint %d not found' % options.checkpoint) + cpts.sort(lambda a,b: cmp(long(a), long(b))) - m5.restoreCheckpoint(root, "/".join([cptdir, "cpt.%s" % cpts[options.checkpoint - 1]])) + if options.checkpoint_restore > len(cpts): + m5.panic('Checkpoint %d not found' % options.checkpoint_restore) + + m5.restoreCheckpoint(root, "/".join([cptdir, "cpt.%s" % cpts[options.checkpoint_restore - 1]])) + +if options.standard_switch: + exit_event = m5.simulate(1000) + ## when you change to Timing (or Atomic), you halt the system given + ## as argument. When you are finished with the system changes + ## (including switchCpus), you must resume the system manually. + ## You DON'T need to resume after just switching CPUs if you haven't + ## changed anything on the system level. + m5.changeToTiming(test_sys) + m5.switchCpus(switch_cpu_list) + m5.resume(test_sys) + + exit_event = m5.simulate(500000000000) + m5.switchCpus(switch_cpu_list1) if options.maxtick: maxtick = options.maxtick @@ -163,17 +224,56 @@ elif options.maxtime: else: maxtick = -1 -exit_event = m5.simulate(maxtick) +num_checkpoints = 0 -while exit_event.getCause() == "checkpoint": - if options.checkpoint_dir: - m5.checkpoint(root, "/".join([options.checkpoint_dir, "cpt.%d"])) - else: - m5.checkpoint(root, "cpt.%d") +exit_cause = '' - if maxtick == -1: - exit_event = m5.simulate(maxtick) - else: - exit_event = m5.simulate(maxtick - m5.curTick()) +if options.take_checkpoints: + [when, period] = options.take_checkpoints.split(",", 1) + when = int(when) + period = int(period) + + exit_event = m5.simulate(when) + while exit_event.getCause() == "checkpoint": + exit_event = m5.simulate(when - m5.curTick()) + + if exit_event.getCause() == "simulate() limit reached": + m5.checkpoint(root, cptdir + "cpt.%d") + num_checkpoints += 1 + + sim_ticks = when + exit_cause = "maximum %d checkpoints dropped" % options.max_checkpoints + while num_checkpoints < options.max_checkpoints: + if (sim_ticks + period) > maxtick and maxtick != -1: + exit_event = m5.simulate(maxtick - sim_ticks) + exit_cause = exit_event.getCause() + break + else: + exit_event = m5.simulate(period) + sim_ticks += period + while exit_event.getCause() == "checkpoint": + exit_event = m5.simulate(period - m5.curTick()) + if exit_event.getCause() == "simulate() limit reached": + m5.checkpoint(root, cptdir + "cpt.%d") + num_checkpoints += 1 + +else: #no checkpoints being taken via this script + exit_event = m5.simulate(maxtick) + + while exit_event.getCause() == "checkpoint": + m5.checkpoint(root, cptdir + "cpt.%d") + num_checkpoints += 1 + if num_checkpoints == options.max_checkpoints: + exit_cause = "maximum %d checkpoints dropped" % options.max_checkpoints + break + + if maxtick == -1: + exit_event = m5.simulate(maxtick) + else: + exit_event = m5.simulate(maxtick - m5.curTick()) + + exit_cause = exit_event.getCause() -print 'Exiting @ cycle', m5.curTick(), 'because', exit_event.getCause() +if exit_cause == '': + exit_cause = exit_event.getCause() +print 'Exiting @ cycle', m5.curTick(), 'because ', exit_cause diff --git a/configs/example/se.py b/configs/example/se.py index 6a941b9da..c4150eed7 100644 --- a/configs/example/se.py +++ b/configs/example/se.py @@ -37,6 +37,7 @@ m5.AddToPath('../common') parser = optparse.OptionParser() +# Benchmark options parser.add_option("-c", "--cmd", default="../../tests/test-progs/hello/bin/alpha/linux/hello", help="The binary to run in syscall emulation mode.") @@ -45,9 +46,35 @@ parser.add_option("-o", "--options", default="", string.") parser.add_option("-i", "--input", default="", help="A file of input to give to the binary.") + +# System options parser.add_option("-d", "--detailed", action="store_true") parser.add_option("-t", "--timing", action="store_true") +parser.add_option("--caches", action="store_true") + +# Run duration options parser.add_option("-m", "--maxtick", type="int") +parser.add_option("--maxtime", type="float") + +#Checkpointing options +###Note that performing checkpointing via python script files will override +###checkpoint instructions built into binaries. +parser.add_option("--take_checkpoints", action="store", type="string", + help="<M,N> will take checkpoint at cycle M and every N cycles \ + thereafter") +parser.add_option("--max_checkpoints", action="store", type="int", + help="the maximum number of checkpoints to drop", + default=5) +parser.add_option("--checkpoint_dir", action="store", type="string", + help="Place all checkpoints in this absolute directory") +parser.add_option("-r", "--checkpoint_restore", action="store", type="int", + help="restore from checkpoint <N>") + +#CPU Switching - default switch model generally goes from a checkpoint +#to a timing simple CPU with caches to warm up, then to detailed CPU for +#data measurement +parser.add_option("-s", "--standard_switch", action="store_true", + help="switch from one cpu mode to another") (options, args) = parser.parse_args() @@ -55,6 +82,13 @@ if args: print "Error: script doesn't take any positional arguments" sys.exit(1) +class MyCache(BaseCache): + assoc = 2 + block_size = 64 + latency = 1 + mshrs = 10 + tgts_per_mshr = 5 + process = LiveProcess() process.executable = options.cmd process.cmd = options.cmd + " " + options.options @@ -93,25 +127,150 @@ cpu.workload = process cpu.cpu_id = 0 system = System(cpu = cpu, - physmem = PhysicalMemory(), + physmem = PhysicalMemory(range=AddrRange("512MB")), membus = Bus()) + +if options.caches and not options.standard_switch: + system.cpu.addPrivateSplitL1Caches(MyCache(size = '32kB'), + MyCache(size = '64kB')) + system.physmem.port = system.membus.port system.cpu.connectMemPorts(system.membus) system.cpu.mem = system.physmem - +system.cpu.clock = '2GHz' root = Root(system = system) if options.timing or options.detailed: root.system.mem_mode = 'timing' +if options.standard_switch: + switch_cpu = TimingSimpleCPU(defer_registration=True, cpu_id=1) + switch_cpu1 = DerivO3CPU(defer_registration=True, cpu_id=2) + switch_cpu.system = system + switch_cpu1.system = system + switch_cpu.clock = cpu.clock + switch_cpu1.clock = cpu.clock + if options.caches: + switch_cpu.addPrivateSplitL1Caches(MyCache(size = '32kB'), + MyCache(size = '64kB')) + + switch_cpu.workload = process + switch_cpu1.workload = process + switch_cpu.mem = system.physmem + switch_cpu1.mem = system.physmem + switch_cpu.connectMemPorts(system.membus) + root.switch_cpu = switch_cpu + root.switch_cpu1 = switch_cpu1 + switch_cpu_list = [(system.cpu, switch_cpu)] + switch_cpu_list1 = [(switch_cpu, switch_cpu1)] + # instantiate configuration m5.instantiate(root) -# simulate until program terminates +if options.checkpoint_dir: + cptdir = options.checkpoint_dir +else: + cptdir = os.getcwd() + +if options.checkpoint_restore: + from os.path import isdir + from os import listdir, getcwd + import re + + if not isdir(cptdir): + m5.panic("checkpoint dir %s does not exist!" % cptdir) + + dirs = listdir(cptdir) + expr = re.compile('cpt.([0-9]*)') + cpts = [] + for dir in dirs: + match = expr.match(dir) + if match: + cpts.append(match.group(1)) + + cpts.sort(lambda a,b: cmp(long(a), long(b))) + + if options.checkpoint_restore > len(cpts): + m5.panic('Checkpoint %d not found' % options.checkpoint_restore) + + print "restoring checkpoint from ","/".join([cptdir, "cpt.%s" % cpts[options.checkpoint_restore - 1]]) + m5.restoreCheckpoint(root, "/".join([cptdir, "cpt.%s" % cpts[options.checkpoint_restore - 1]])) + +if options.standard_switch: + exit_event = m5.simulate(10000) + ## when you change to Timing (or Atomic), you halt the system given + ## as argument. When you are finished with the system changes + ## (including switchCpus), you must resume the system manually. + ## You DON'T need to resume after just switching CPUs if you haven't + ## changed anything on the system level. + m5.changeToTiming(system) + m5.switchCpus(switch_cpu_list) + m5.resume(system) + + exit_event = m5.simulate(500000000000) + m5.switchCpus(switch_cpu_list1) + if options.maxtick: - exit_event = m5.simulate(options.maxtick) + maxtick = options.maxtick +elif options.maxtime: + simtime = int(options.maxtime * root.clock.value) + print "simulating for: ", simtime + maxtick = simtime else: - exit_event = m5.simulate() + maxtick = -1 + +num_checkpoints = 0 + +exit_cause = '' + +if options.take_checkpoints: + [when, period] = options.take_checkpoints.split(",", 1) + when = int(when) + period = int(period) + + exit_event = m5.simulate(when) + while exit_event.getCause() == "checkpoint": + exit_event = m5.simulate(when - m5.curTick()) + + if exit_event.getCause() == "simulate() limit reached": + m5.checkpoint(root, cptdir + "cpt.%d") + num_checkpoints += 1 + + sim_ticks = when + exit_cause = "maximum %d checkpoints dropped" % options.max_checkpoints + while num_checkpoints < options.max_checkpoints: + if (sim_ticks + period) > maxtick and maxtick != -1: + exit_event = m5.simulate(maxtick - sim_ticks) + exit_cause = exit_event.getCause() + break + else: + exit_event = m5.simulate(period) + sim_ticks += period + while exit_event.getCause() == "checkpoint": + exit_event = m5.simulate(period - m5.curTick()) + if exit_event.getCause() == "simulate() limit reached": + m5.checkpoint(root, cptdir + "cpt.%d") + num_checkpoints += 1 + +else: #no checkpoints being taken via this script + exit_event = m5.simulate(maxtick) + + while exit_event.getCause() == "checkpoint": + m5.checkpoint(root, cptdir + "cpt.%d") + num_checkpoints += 1 + if num_checkpoints == options.max_checkpoints: + exit_cause = "maximum %d checkpoints dropped" % options.max_checkpoints + break + + if maxtick == -1: + exit_event = m5.simulate(maxtick) + else: + exit_event = m5.simulate(maxtick - m5.curTick()) + + exit_cause = exit_event.getCause() + +if exit_cause == '': + exit_cause = exit_event.getCause() +print 'Exiting @ cycle', m5.curTick(), 'because ', exit_cause -print 'Exiting @ tick', m5.curTick(), 'because', exit_event.getCause() diff --git a/src/base/traceflags.py b/src/base/traceflags.py index 2402cf361..92735aa5f 100644 --- a/src/base/traceflags.py +++ b/src/base/traceflags.py @@ -84,6 +84,7 @@ baseFlags = [ 'EthernetDMA', 'EthernetData', 'EthernetDesc', + 'EthernetEEPROM', 'EthernetIntr', 'EthernetPIO', 'EthernetSM', diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 25c478ae9..edba55b0d 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -183,11 +183,14 @@ AtomicSimpleCPU::unserialize(Checkpoint *cp, const string §ion) void AtomicSimpleCPU::resume() { - changeState(SimObject::Running); - if (thread->status() == ThreadContext::Active) { + if (_status != SwitchedOut && _status != Idle) { assert(system->getMemoryMode() == System::Atomic); - if (!tickEvent.scheduled()) - tickEvent.schedule(curTick); + + changeState(SimObject::Running); + if (thread->status() == ThreadContext::Active) { + if (!tickEvent.scheduled()) + tickEvent.schedule(curTick); + } } } diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index 943e6881f..e52a3e73d 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -30,6 +30,9 @@ /* @file * Device model for Intel's 8254x line of gigabit ethernet controllers. + * In particular an 82547 revision 2 (82547GI) MAC because it seems to have the + * fewest workarounds in the driver. It will probably work with most of the + * other MACs with slight modifications. */ #include "base/inet.hh" @@ -39,10 +42,38 @@ #include "sim/stats.hh" #include "sim/system.hh" +using namespace iGbReg; + IGbE::IGbE(Params *p) : PciDev(p), etherInt(NULL) { - + // Initialized internal registers per Intel documentation + regs.tctl.reg = 0; + regs.rctl.reg = 0; + regs.ctrl.reg = 0; + regs.ctrl.fd = 1; + regs.ctrl.lrst = 1; + regs.ctrl.speed = 2; + regs.ctrl.frcspd = 1; + regs.sts.reg = 0; + regs.eecd.reg = 0; + regs.eecd.fwe = 1; + regs.eecd.ee_type = 1; + regs.eerd.reg = 0; + regs.icd.reg = 0; + regs.imc.reg = 0; + regs.rctl.reg = 0; + regs.tctl.reg = 0; + regs.manc.reg = 0; + + eeOpBits = 0; + eeAddrBits = 0; + eeDataBits = 0; + eeOpcode = 0; + + memset(&flash, 0, EEPROM_SIZE); + // Magic happy checksum value + flash[0] = 0xBABA; } @@ -74,15 +105,49 @@ IGbE::read(PacketPtr pkt) // Only Memory register BAR is allowed assert(bar == 0); - DPRINTF(Ethernet, "Accessed devie register %#X\n", daddr); + // Only 32bit accesses allowed + assert(pkt->getSize() == 4); - pkt->allocate(); + DPRINTF(Ethernet, "Read device register %#X\n", daddr); + pkt->allocate(); /// /// Handle read of register here /// + switch (daddr) { + case CTRL: + pkt->set<uint32_t>(regs.ctrl.reg); + break; + case STATUS: + pkt->set<uint32_t>(regs.sts.reg); + break; + case EECD: + pkt->set<uint32_t>(regs.eecd.reg); + break; + case EERD: + pkt->set<uint32_t>(regs.eerd.reg); + break; + case ICR: + pkt->set<uint32_t>(regs.icd.reg); + break; + case IMC: + pkt->set<uint32_t>(regs.imc.reg); + break; + case RCTL: + pkt->set<uint32_t>(regs.rctl.reg); + break; + case TCTL: + pkt->set<uint32_t>(regs.tctl.reg); + break; + case MANC: + pkt->set<uint32_t>(regs.manc.reg); + break; + default: + panic("Read request to unknown register number: %#x\n", daddr); + }; + pkt->result = Packet::Success; return pioDelay; } @@ -93,17 +158,100 @@ IGbE::write(PacketPtr pkt) int bar; Addr daddr; + if (!getBAR(pkt->getAddr(), bar, daddr)) panic("Invalid PCI memory access to unmapped memory.\n"); // Only Memory register BAR is allowed assert(bar == 0); - DPRINTF(Ethernet, "Accessed devie register %#X\n", daddr); + // Only 32bit accesses allowed + assert(pkt->getSize() == sizeof(uint32_t)); + + DPRINTF(Ethernet, "Wrote device register %#X value %#X\n", daddr, pkt->get<uint32_t>()); /// /// Handle write of register here /// + uint32_t val = pkt->get<uint32_t>(); + + switch (daddr) { + case CTRL: + regs.ctrl.reg = val; + break; + case STATUS: + regs.sts.reg = val; + break; + case EECD: + int oldClk; + oldClk = regs.eecd.sk; + regs.eecd.reg = val; + // See if this is a eeprom access and emulate accordingly + if (!oldClk && regs.eecd.sk) { + if (eeOpBits < 8) { + eeOpcode = eeOpcode << 1 | regs.eecd.din; + eeOpBits++; + } else if (eeAddrBits < 8 && eeOpcode == EEPROM_READ_OPCODE_SPI) { + eeAddr = eeAddr << 1 | regs.eecd.din; + eeAddrBits++; + } else if (eeDataBits < 16 && eeOpcode == EEPROM_READ_OPCODE_SPI) { + assert(eeAddr < EEPROM_SIZE); + DPRINTF(Ethernet, "EEPROM bit read: %d word: %#X\n", + flash[eeAddr] >> eeDataBits & 0x1, flash[eeAddr]); + regs.eecd.dout = (flash[eeAddr] >> eeDataBits) & 0x1; + eeDataBits++; + } else if (eeDataBits < 8 && eeOpcode == EEPROM_RDSR_OPCODE_SPI) { + regs.eecd.dout = 0; + eeDataBits++; + } else + panic("What's going on with eeprom interface? opcode:" + " %#x:%d addr: %#x:%d, data: %d\n", (uint32_t)eeOpcode, + (uint32_t)eeOpBits, (uint32_t)eeAddr, + (uint32_t)eeAddrBits, (uint32_t)eeDataBits); + + // Reset everything for the next command + if ((eeDataBits == 16 && eeOpcode == EEPROM_READ_OPCODE_SPI) || + (eeDataBits == 8 && eeOpcode == EEPROM_RDSR_OPCODE_SPI)) { + eeOpBits = 0; + eeAddrBits = 0; + eeDataBits = 0; + eeOpcode = 0; + eeAddr = 0; + } + + DPRINTF(Ethernet, "EEPROM: opcode: %#X:%d\n", + (uint32_t)eeOpcode, (uint32_t) eeOpBits); + if (eeOpBits == 8 && !(eeOpcode == EEPROM_READ_OPCODE_SPI || + eeOpcode == EEPROM_RDSR_OPCODE_SPI )) + panic("Unknown eeprom opcode: %#X:%d\n", (uint32_t)eeOpcode, + (uint32_t)eeOpBits); + + + } + // If driver requests eeprom access, immediately give it to it + regs.eecd.ee_gnt = regs.eecd.ee_req; + break; + case EERD: + regs.eerd.reg = val; + break; + case ICR: + regs.icd.reg = val; + break; + case IMC: + regs.imc.reg = val; + break; + case RCTL: + regs.rctl.reg = val; + break; + case TCTL: + regs.tctl.reg = val; + break; + case MANC: + regs.manc.reg = val; + break; + default: + panic("Write request to unknown register number: %#x\n", daddr); + }; pkt->result = Packet::Success; return pioDelay; diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh index 161d8befc..ce4007263 100644 --- a/src/dev/i8254xGBe.hh +++ b/src/dev/i8254xGBe.hh @@ -39,6 +39,7 @@ #include "base/statistics.hh" #include "dev/etherint.hh" #include "dev/etherpkt.hh" +#include "dev/i8254xGBe_defs.hh" #include "dev/pcidev.hh" #include "dev/pktfifo.hh" #include "sim/eventq.hh" @@ -49,6 +50,12 @@ class IGbE : public PciDev { private: IGbEInt *etherInt; + iGbReg::Regs regs; + int eeOpBits, eeAddrBits, eeDataBits; + uint8_t eeOpcode, eeAddr; + + uint16_t flash[iGbReg::EEPROM_SIZE]; + public: struct Params : public PciDev::Params diff --git a/src/dev/i8254xGBe_defs.hh b/src/dev/i8254xGBe_defs.hh index 81d7d0d80..ae0925356 100644 --- a/src/dev/i8254xGBe_defs.hh +++ b/src/dev/i8254xGBe_defs.hh @@ -34,17 +34,18 @@ namespace iGbReg { -const uint32_t CTRL = 0x00000; -const uint32_t STATUS = 0x00008; -const uint32_t EECD = 0x00010; +const uint32_t CTRL = 0x00000; //* +const uint32_t STATUS = 0x00008; //* +const uint32_t EECD = 0x00010; //* +const uint32_t EERD = 0x00014; //* const uint32_t CTRL_EXT = 0x00018; const uint32_t PBA = 0x01000; -const uint32_t ICR = 0x000C0; +const uint32_t ICR = 0x000C0; //* const uint32_t ITR = 0x000C4; const uint32_t ICS = 0x000C8; const uint32_t IMS = 0x000D0; -const uint32_t IMC = 0x000D8; -const uint32_t RCTL = 0x00100; +const uint32_t IMC = 0x000D8; //* +const uint32_t RCTL = 0x00100; //* const uint32_t RDBAL = 0x02800; const uint32_t RDBAH = 0x02804; const uint32_t RDLEN = 0x02808; @@ -53,7 +54,7 @@ const uint32_t RDT = 0x02818; const uint32_t RDTR = 0x02820; const uint32_t RADV = 0x0282C; const uint32_t RSRPD = 0x02C00; -const uint32_t TCTL = 0x00400; +const uint32_t TCTL = 0x00400; //* const uint32_t TDBAL = 0x03800; const uint32_t TDBAH = 0x03804; const uint32_t TDLEN = 0x03808; @@ -66,6 +67,11 @@ const uint32_t TADV = 0x0282C; const uint32_t TSPMT = 0x03830; const uint32_t RXDCTL = 0x02828; const uint32_t RXCSUM = 0x05000; +const uint32_t MANC = 0x05820;//* + +const uint8_t EEPROM_READ_OPCODE_SPI = 0x03; +const uint8_t EEPROM_RDSR_OPCODE_SPI = 0x05; +const uint8_t EEPROM_SIZE = 64; struct RxDesc { Addr buf; @@ -239,4 +245,219 @@ union TxDesc { } type; }; +struct Regs { + union { // 0x0000 CTRL Register + uint32_t reg; + struct { + uint8_t fd:1; // full duplex + uint8_t bem:1; // big endian mode + uint8_t pcipr:1; // PCI priority + uint8_t lrst:1; // link reset + uint8_t tme:1; // test mode enable + uint8_t asde:1; // Auto-speed detection + uint8_t slu:1; // Set link up + uint8_t ilos:1; // invert los-of-signal + uint8_t speed:2; // speed selection bits + uint8_t be32:1; // big endian mode 32 + uint8_t frcspd:1; // force speed + uint8_t frcdpx:1; // force duplex + uint8_t duden:1; // dock/undock enable + uint8_t dudpol:1; // dock/undock polarity + uint8_t fphyrst:1; // force phy reset + uint8_t extlen:1; // external link status enable + uint8_t rsvd:1; // reserved + uint8_t sdp0d:1; // software controlled pin data + uint8_t sdp1d:1; // software controlled pin data + uint8_t sdp2d:1; // software controlled pin data + uint8_t sdp3d:1; // software controlled pin data + uint8_t sdp0i:1; // software controlled pin dir + uint8_t sdp1i:1; // software controlled pin dir + uint8_t sdp2i:1; // software controlled pin dir + uint8_t sdp3i:1; // software controlled pin dir + uint8_t rst:1; // reset + uint8_t rfce:1; // receive flow control enable + uint8_t tfce:1; // transmit flow control enable + uint8_t rte:1; // routing tag enable + uint8_t vme:1; // vlan enable + uint8_t phyrst:1; // phy reset + } ; + } ctrl; + + union { // 0x0008 STATUS + uint32_t reg; + struct { + uint8_t fd:1; // full duplex + uint8_t lu:1; // link up + uint8_t func:2; // function id + uint8_t txoff:1; // transmission paused + uint8_t tbimode:1; // tbi mode + uint8_t speed:2; // link speed + uint8_t asdv:2; // auto speed detection value + uint8_t mtxckok:1; // mtx clock running ok + uint8_t pci66:1; // In 66Mhz pci slot + uint8_t bus64:1; // in 64 bit slot + uint8_t pcix:1; // Pci mode + uint8_t pcixspd:1; // pci x speed + uint8_t reserved; // reserved + } ; + } sts; + + union { // 0x0010 EECD + uint32_t reg; + struct { + uint8_t sk:1; // clack input to the eeprom + uint8_t cs:1; // chip select to eeprom + uint8_t din:1; // data input to eeprom + uint8_t dout:1; // data output bit + uint8_t fwe:2; // flash write enable + uint8_t ee_req:1; // request eeprom access + uint8_t ee_gnt:1; // grant eeprom access + uint8_t ee_pres:1; // eeprom present + uint8_t ee_size:1; // eeprom size + uint8_t ee_sz1:1; // eeprom size + uint8_t rsvd:2; // reserved + uint8_t ee_type:1; // type of eeprom + } ; + } eecd; + + union { // 0x0014 EERD + uint32_t reg; + struct { + uint8_t start:1; // start read + uint8_t done:1; // done read + uint16_t addr:14; // address + uint16_t data; // data + }; + } eerd; + + union { // 0x00C0 ICR + uint32_t reg; + struct { + uint8_t txdw:1; // tx descr witten back + uint8_t txqe:1; // tx queue empty + uint8_t lsc:1; // link status change + uint8_t rxseq:1; // rcv sequence error + uint8_t rxdmt0:1; // rcv descriptor min thresh + uint8_t rsvd1:1; // reserved + uint8_t rxo:1; // receive overrunn + uint8_t rxt0:1; // receiver timer interrupt + uint8_t rsvd2:1; // reserved + uint8_t mdac:1; // mdi/o access complete + uint8_t rxcfg:1; // recv /c/ ordered sets + uint8_t rsvd3:1; // reserved + uint8_t phyint:1; // phy interrupt + uint8_t gpi1:1; // gpi int 1 + uint8_t gpi2:1; // gpi int 2 + uint8_t txdlow:1; // transmit desc low thresh + uint8_t srpd:1; // small receive packet detected + uint16_t rsvd4:15; // reserved + } ; + } icd; + + union { // 0x00C0 IMC + uint32_t reg; + struct { + uint8_t txdw:1; // tx descr witten back + uint8_t txqe:1; // tx queue empty + uint8_t lsc:1; // link status change + uint8_t rxseq:1; // rcv sequence error + uint8_t rxdmt0:1; // rcv descriptor min thresh + uint8_t rsvd1:1; // reserved + uint8_t rxo:1; // receive overrunn + uint8_t rxt0:1; // receiver timer interrupt + uint8_t rsvd2:1; // reserved + uint8_t mdac:1; // mdi/o access complete + uint8_t rxcfg:1; // recv /c/ ordered sets + uint8_t rsvd3:1; // reserved + uint8_t phyint:1; // phy interrupt + uint8_t gpi1:1; // gpi int 1 + uint8_t gpi2:1; // gpi int 2 + uint8_t txdlow:1; // transmit desc low thresh + uint8_t srpd:1; // small receive packet detected + uint16_t rsvd4:15; // reserved + } ; + } imc; + + union { // 0x0100 RCTL + uint32_t reg; + struct { + uint8_t rst:1; // Reset + uint8_t en:1; // Enable + uint8_t sbp:1; // Store bad packets + uint8_t upe:1; // Unicast Promiscuous enabled + uint8_t mpe:1; // Multicast promiscuous enabled + uint8_t lpe:1; // long packet reception enabled + uint8_t lbm:2; // + uint8_t rdmts:2; // + uint8_t rsvd:2; // + uint8_t mo:2; // + uint8_t mdr:1; // + uint8_t bam:1; // + uint8_t bsize:2; // + uint8_t vpe:1; // + uint8_t cfien:1; // + uint8_t cfi:1; // + uint8_t rsvd2:1; // + uint8_t dpf:1; // discard pause frames + uint8_t pmcf:1; // pass mac control frames + uint8_t rsvd3:1; // reserved + uint8_t bsex:1; // buffer size extension + uint8_t secrc:1; // strip ethernet crc from incoming packet + uint8_t rsvd1:5; // reserved + } ; + } rctl; + + union { // 0x0400 TCTL + uint32_t reg; + struct { + uint8_t rst:1; // Reset + uint8_t en:1; // Enable + uint8_t bce:1; // busy check enable + uint8_t psp:1; // pad short packets + uint8_t ct:8; // collision threshold + uint16_t cold:10; // collision distance + uint8_t swxoff:1; // software xoff transmission + uint8_t pbe:1; // packet burst enable + uint8_t rtlc:1; // retransmit late collisions + uint8_t nrtu:1; // on underrun no TX + uint8_t mulr:1; // multiple request + uint8_t rsvd:5; // reserved + } ; + } tctl; + + union { // 0x5820 MANC + uint32_t reg; + struct { + uint8_t smbus:1; // SMBus enabled ##### + uint8_t asf:1; // ASF enabled ##### + uint8_t ronforce:1; // reset of force + uint8_t rsvd:5; // reserved + uint8_t rmcp1:1; // rcmp1 filtering + uint8_t rmcp2:1; // rcmp2 filtering + uint8_t ipv4:1; // enable ipv4 + uint8_t ipv6:1; // enable ipv6 + uint8_t snap:1; // accept snap + uint8_t arp:1; // filter arp ##### + uint8_t neighbor:1; // neighbor discovery + uint8_t arp_resp:1; // arp response + uint8_t tcorst:1; // tco reset happened + uint8_t rcvtco:1; // receive tco enabled ###### + uint8_t blkphyrst:1;// block phy resets ######## + uint8_t rcvall:1; // receive all + uint8_t macaddrfltr:1; // mac address filtering ###### + uint8_t mng2host:1; // mng2 host packets ####### + uint8_t ipaddrfltr:1; // ip address filtering + uint8_t xsumfilter:1; // checksum filtering + uint8_t brfilter:1; // broadcast filtering + uint8_t smbreq:1; // smb request + uint8_t smbgnt:1; // smb grant + uint8_t smbclkin:1; // smbclkin + uint8_t smbdatain:1; // smbdatain + uint8_t smbdataout:1; // smb data out + uint8_t smbclkout:1; // smb clock out + uint8_t rsvd2:2; + }; + } manc; +}; + }; // iGbReg namespace diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc index 0694aae6e..599958222 100644 --- a/src/mem/cache/base_cache.cc +++ b/src/mem/cache/base_cache.cc @@ -79,9 +79,7 @@ BaseCache::CachePort::recvTiming(PacketPtr pkt) && !pkt->isRead() && !pkt->isWrite()) { //Upgrade or Invalidate //Look into what happens if two slave caches on bus - DPRINTF(Cache, "%s %x ? blk_addr: %x\n", pkt->cmdString(), - pkt->getAddr() & (((ULL(1))<<48)-1), - pkt->getAddr() & ~((Addr)cache->blkSize - 1)); + DPRINTF(Cache, "%s %x ?\n", pkt->cmdString(), pkt->getAddr()); assert(!(pkt->flags & SATISFIED)); pkt->flags |= SATISFIED; diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 3c47762f6..9bb72e85c 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -205,9 +205,10 @@ Cache<TagStore,Buffering,Coherence>::access(PacketPtr &pkt) missQueue->doWriteback(writebacks.front()); writebacks.pop_front(); } - DPRINTF(Cache, "%s %x %s blk_addr: %x\n", pkt->cmdString(), - pkt->getAddr() & (((ULL(1))<<48)-1), (blk) ? "hit" : "miss", - pkt->getAddr() & ~((Addr)blkSize - 1)); + + DPRINTF(Cache, "%s %x %s\n", pkt->cmdString(), pkt->getAddr(), + (blk) ? "hit" : "miss"); + if (blk) { // Hit hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++; @@ -288,10 +289,8 @@ Cache<TagStore,Buffering,Coherence>::sendResult(PacketPtr &pkt, MSHR* mshr, CacheBlk::State old_state = (blk) ? blk->status : 0; CacheBlk::State new_state = coherence->getNewState(pkt,old_state); if (old_state != new_state) - DPRINTF(Cache, "Block for blk addr %x moving from " - "state %i to %i\n", - pkt->getAddr() & (((ULL(1))<<48)-1), - old_state, new_state); + DPRINTF(Cache, "Block for blk addr %x moving from state " + "%i to %i\n", pkt->getAddr(), old_state, new_state); //Set the state on the upgrade memcpy(pkt->getPtr<uint8_t>(), blk->data, blkSize); PacketList writebacks; @@ -331,8 +330,7 @@ Cache<TagStore,Buffering,Coherence>::handleResponse(PacketPtr &pkt) //Make the response a Bad address and send it } // MemDebug::cacheResponse(pkt); - DPRINTF(Cache, "Handling reponse to %x, blk addr: %x\n",pkt->getAddr(), - pkt->getAddr() & (((ULL(1))<<48)-1)); + DPRINTF(Cache, "Handling reponse to %x\n", pkt->getAddr()); if (pkt->isCacheFill() && !pkt->isNoAllocate()) { blk = tags->findBlock(pkt); @@ -342,7 +340,7 @@ Cache<TagStore,Buffering,Coherence>::handleResponse(PacketPtr &pkt) if (old_state != new_state) DPRINTF(Cache, "Block for blk addr %x moving from " "state %i to %i\n", - pkt->getAddr() & (((ULL(1))<<48)-1), + pkt->getAddr(), old_state, new_state); blk = tags->handleFill(blk, (MSHR*)pkt->senderState, new_state, writebacks, pkt); @@ -427,8 +425,8 @@ Cache<TagStore,Buffering,Coherence>::snoop(PacketPtr &pkt) //Append the invalidate on missQueue->addTarget(mshr,invalidatePkt); - DPRINTF(Cache, "Appending Invalidate to blk_addr: %x\n", - pkt->getAddr() & (((ULL(1))<<48)-1)); + DPRINTF(Cache, "Appending Invalidate to addr: %x\n", + pkt->getAddr()); return; } } @@ -436,8 +434,8 @@ Cache<TagStore,Buffering,Coherence>::snoop(PacketPtr &pkt) //We also need to check the writeback buffers and handle those std::vector<MSHR *> writebacks; if (missQueue->findWrites(blk_addr, writebacks)) { - DPRINTF(Cache, "Snoop hit in writeback to blk_addr: %x\n", - pkt->getAddr() & (((ULL(1))<<48)-1)); + DPRINTF(Cache, "Snoop hit in writeback to addr: %x\n", + pkt->getAddr()); //Look through writebacks for any non-uncachable writes, use that for (int i=0; i<writebacks.size(); i++) { @@ -528,12 +526,9 @@ Cache<TagStore,Buffering,Coherence>::probe(PacketPtr &pkt, bool update, { // MemDebug::cacheProbe(pkt); if (!pkt->req->isUncacheable()) { - if (pkt->isInvalidate() && !pkt->isRead() - && !pkt->isWrite()) { + if (pkt->isInvalidate() && !pkt->isRead() && !pkt->isWrite()) { //Upgrade or Invalidate, satisfy it, don't forward - DPRINTF(Cache, "%s %x ? blk_addr: %x\n", pkt->cmdString(), - pkt->getAddr() & (((ULL(1))<<48)-1), - pkt->getAddr() & ~((Addr)blkSize - 1)); + DPRINTF(Cache, "%s %x ?\n", pkt->cmdString(), pkt->getAddr()); pkt->flags |= SATISFIED; return 0; } @@ -550,9 +545,8 @@ Cache<TagStore,Buffering,Coherence>::probe(PacketPtr &pkt, bool update, int lat; BlkType *blk = tags->handleAccess(pkt, lat, writebacks, update); - DPRINTF(Cache, "%s %x %s blk_addr: %x\n", pkt->cmdString(), - pkt->getAddr() & (((ULL(1))<<48)-1), (blk) ? "hit" : "miss", - pkt->getAddr() & ~((Addr)blkSize - 1)); + DPRINTF(Cache, "%s %x %s\n", pkt->cmdString(), + pkt->getAddr(), (blk) ? "hit" : "miss"); // Need to check for outstanding misses and writes @@ -596,7 +590,7 @@ Cache<TagStore,Buffering,Coherence>::probe(PacketPtr &pkt, bool update, } else if (!blk && !(pkt->flags & SATISFIED)) { // update the cache state and statistics if (mshr || !writes.empty()){ - // Can't handle it, return pktuest unsatisfied. + // Can't handle it, return request unsatisfied. panic("Atomic access ran into outstanding MSHR's or WB's!"); } if (!pkt->req->isUncacheable()) { @@ -611,10 +605,8 @@ Cache<TagStore,Buffering,Coherence>::probe(PacketPtr &pkt, bool update, busPkt->time = curTick; - DPRINTF(Cache, "Sending a atomic %s for %x blk_addr: %x\n", - busPkt->cmdString(), - busPkt->getAddr() & (((ULL(1))<<48)-1), - busPkt->getAddr() & ~((Addr)blkSize - 1)); + DPRINTF(Cache, "Sending a atomic %s for %x\n", + busPkt->cmdString(), busPkt->getAddr()); lat = memSidePort->sendAtomic(busPkt); @@ -633,19 +625,13 @@ return 0; CacheBlk::State old_state = (blk) ? blk->status : 0; CacheBlk::State new_state = coherence->getNewState(busPkt, old_state); - DPRINTF(Cache, - "Receive response:%s for blk addr %x in state %i\n", - busPkt->cmdString(), - busPkt->getAddr() & (((ULL(1))<<48)-1), old_state); + DPRINTF(Cache, "Receive response: %s for addr %x in state %i\n", + busPkt->cmdString(), busPkt->getAddr(), old_state); if (old_state != new_state) - DPRINTF(Cache, "Block for blk addr %x moving from " - "state %i to %i\n", - busPkt->getAddr() & (((ULL(1))<<48)-1), - old_state, new_state); - - tags->handleFill(blk, busPkt, - new_state, - writebacks, pkt); + DPRINTF(Cache, "Block for blk addr %x moving from state " + "%i to %i\n", busPkt->getAddr(), old_state, new_state); + + tags->handleFill(blk, busPkt, new_state, writebacks, pkt); //Free the packet delete busPkt; diff --git a/src/mem/cache/miss/blocking_buffer.hh b/src/mem/cache/miss/blocking_buffer.hh index 4408cfc4f..934a843a6 100644 --- a/src/mem/cache/miss/blocking_buffer.hh +++ b/src/mem/cache/miss/blocking_buffer.hh @@ -128,8 +128,8 @@ public: } /** - * Selects a outstanding pktuest to service. - * @return The pktuest to service, NULL if none found. + * Selects a outstanding request to service. + * @return The request to service, NULL if none found. */ PacketPtr getPacket(); @@ -147,7 +147,7 @@ public: void restoreOrigCmd(PacketPtr &pkt); /** - * Marks a pktuest as in service (sent on the bus). This can have side + * Marks a request as in service (sent on the bus). This can have side * effect since storage for no response commands is deallocated once they * are successfully sent. * @param pkt The request that was sent on the bus. @@ -155,14 +155,14 @@ public: void markInService(PacketPtr &pkt, MSHR* mshr); /** - * Frees the resources of the pktuest and unblock the cache. + * Frees the resources of the request and unblock the cache. * @param pkt The request that has been satisfied. - * @param time The time when the pktuest is satisfied. + * @param time The time when the request is satisfied. */ void handleResponse(PacketPtr &pkt, Tick time); /** - * Removes all outstanding pktuests for a given thread number. If a request + * Removes all outstanding requests for a given thread number. If a request * has been sent to the bus, this function removes all of its targets. * @param threadNum The thread number of the requests to squash. */ @@ -220,14 +220,14 @@ public: int size, uint8_t *data, bool compressed); /** - * Perform a writeback pktuest. + * Perform a writeback request. * @param pkt The writeback request. */ void doWriteback(PacketPtr &pkt); /** - * Returns true if there are outstanding pktuests. - * @return True if there are outstanding pktuests. + * Returns true if there are outstanding requests. + * @return True if there are outstanding requests. */ bool havePending() { diff --git a/src/mem/cache/miss/miss_queue.hh b/src/mem/cache/miss/miss_queue.hh index 2e04802fb..b67a896f4 100644 --- a/src/mem/cache/miss/miss_queue.hh +++ b/src/mem/cache/miss/miss_queue.hh @@ -77,7 +77,7 @@ class MissQueue /** The block size of the parent cache. */ int blkSize; - /** Increasing order number assigned to each incoming pktuest. */ + /** Increasing order number assigned to each incoming request. */ uint64_t order; bool prefetchMiss; @@ -212,7 +212,7 @@ class MissQueue void setPrefetcher(BasePrefetcher *_prefetcher); /** - * Handle a cache miss properly. Either allocate an MSHR for the pktuest, + * Handle a cache miss properly. Either allocate an MSHR for the request, * or forward it through the write buffer. * @param pkt The request that missed in the cache. * @param blk_size The block size of the cache. @@ -232,8 +232,8 @@ class MissQueue PacketPtr &target); /** - * Selects a outstanding pktuest to service. - * @return The pktuest to service, NULL if none found. + * Selects a outstanding request to service. + * @return The request to service, NULL if none found. */ PacketPtr getPacket(); @@ -251,7 +251,7 @@ class MissQueue void restoreOrigCmd(PacketPtr &pkt); /** - * Marks a pktuest as in service (sent on the bus). This can have side + * Marks a request as in service (sent on the bus). This can have side * effect since storage for no response commands is deallocated once they * are successfully sent. * @param pkt The request that was sent on the bus. @@ -259,14 +259,14 @@ class MissQueue void markInService(PacketPtr &pkt, MSHR* mshr); /** - * Collect statistics and free resources of a satisfied pktuest. + * Collect statistics and free resources of a satisfied request. * @param pkt The request that has been satisfied. - * @param time The time when the pktuest is satisfied. + * @param time The time when the request is satisfied. */ void handleResponse(PacketPtr &pkt, Tick time); /** - * Removes all outstanding pktuests for a given thread number. If a request + * Removes all outstanding requests for a given thread number. If a request * has been sent to the bus, this function removes all of its targets. * @param threadNum The thread number of the requests to squash. */ @@ -313,14 +313,14 @@ class MissQueue int size, uint8_t *data, bool compressed); /** - * Perform the given writeback pktuest. + * Perform the given writeback request. * @param pkt The writeback request. */ void doWriteback(PacketPtr &pkt); /** - * Returns true if there are outstanding pktuests. - * @return True if there are outstanding pktuests. + * Returns true if there are outstanding requests. + * @return True if there are outstanding requests. */ bool havePending(); diff --git a/src/mem/cache/miss/mshr.hh b/src/mem/cache/miss/mshr.hh index d92aa8a85..281ea9d49 100644 --- a/src/mem/cache/miss/mshr.hh +++ b/src/mem/cache/miss/mshr.hh @@ -44,7 +44,7 @@ class MSHR; /** * Miss Status and handling Register. This class keeps all the information - * needed to handle a cache miss including a list of target pktuests. + * needed to handle a cache miss including a list of target requests. */ class MSHR { public: @@ -63,15 +63,15 @@ class MSHR { Addr addr; /** Adress space id of the miss. */ short asid; - /** True if the pktuest has been sent to the bus. */ + /** True if the request has been sent to the bus. */ bool inService; /** Thread number of the miss. */ int threadNum; - /** The pktuest that is forwarded to the next level of the hierarchy. */ + /** The request that is forwarded to the next level of the hierarchy. */ PacketPtr pkt; /** The number of currently allocated targets. */ short ntargets; - /** The original pktuesting command. */ + /** The original requesting command. */ Packet::Command originalCmd; /** Order number of assigned by the miss queue. */ uint64_t order; @@ -88,24 +88,24 @@ class MSHR { Iterator allocIter; private: - /** List of all pktuests that match the address */ + /** List of all requests that match the address */ TargetList targets; public: /** * Allocate a miss to this MSHR. - * @param cmd The pktuesting command. + * @param cmd The requesting command. * @param addr The address of the miss. * @param asid The address space id of the miss. - * @param size The number of bytes to pktuest. + * @param size The number of bytes to request. * @param pkt The original miss. */ void allocate(Packet::Command cmd, Addr addr, int size, PacketPtr &pkt); /** - * Allocate this MSHR as a buffer for the given pktuest. - * @param target The memory pktuest to buffer. + * Allocate this MSHR as a buffer for the given request. + * @param target The memory request to buffer. */ void allocateAsBuffer(PacketPtr &target); @@ -115,7 +115,7 @@ public: void deallocate(); /** - * Add a pktuest to the list of targets. + * Add a request to the list of targets. * @param target The target. */ void allocateTarget(PacketPtr &target); diff --git a/src/mem/cache/miss/mshr_queue.hh b/src/mem/cache/miss/mshr_queue.hh index 30397d9a0..ec2ddae8a 100644 --- a/src/mem/cache/miss/mshr_queue.hh +++ b/src/mem/cache/miss/mshr_queue.hh @@ -39,7 +39,7 @@ #include "mem/cache/miss/mshr.hh" /** - * A Class for maintaining a list of pending and allocated memory pktuests. + * A Class for maintaining a list of pending and allocated memory requests. */ class MSHRQueue { private: @@ -55,7 +55,7 @@ class MSHRQueue { // Parameters /** * The total number of MSHRs in this queue. This number is set as the - * number of MSHRs pktuested plus (numReserve - 1). This allows for + * number of MSHRs requested plus (numReserve - 1). This allows for * the same number of effective MSHRs while still maintaining the reserve. */ const int numMSHRs; @@ -103,14 +103,14 @@ class MSHRQueue { bool findMatches(Addr addr, std::vector<MSHR*>& matches) const; /** - * Find any pending pktuests that overlap the given request. + * Find any pending requests that overlap the given request. * @param pkt The request to find. * @return A pointer to the earliest matching MSHR. */ MSHR* findPending(PacketPtr &pkt) const; /** - * Allocates a new MSHR for the pktuest and size. This places the request + * Allocates a new MSHR for the request and size. This places the request * as the first target in the MSHR. * @param pkt The request to handle. * @param size The number in bytes to fetch from memory. @@ -121,12 +121,12 @@ class MSHRQueue { MSHR* allocate(PacketPtr &pkt, int size = 0); /** - * Allocate a read pktuest for the given address, and places the given + * Allocate a read request for the given address, and places the given * target on the target list. * @param addr The address to fetch. * @param asid The address space for the fetch. - * @param size The number of bytes to pktuest. - * @param target The first target for the pktuest. + * @param size The number of bytes to request. + * @param target The first target for the request. * @return Pointer to the new MSHR. */ MSHR* allocateFetch(Addr addr, int size, PacketPtr &target); @@ -135,7 +135,7 @@ class MSHRQueue { * Allocate a target list for the given address. * @param addr The address to fetch. * @param asid The address space for the fetch. - * @param size The number of bytes to pktuest. + * @param size The number of bytes to request. * @return Pointer to the new MSHR. */ MSHR* allocateTargetList(Addr addr, int size); @@ -181,14 +181,14 @@ class MSHRQueue { void markInService(MSHR* mshr); /** - * Mark an in service mshr as pending, used to resend a pktuest. + * Mark an in service mshr as pending, used to resend a request. * @param mshr The MSHR to resend. * @param cmd The command to resend. */ void markPending(MSHR* mshr, Packet::Command cmd); /** - * Squash outstanding pktuests with the given thread number. If a request + * Squash outstanding requests with the given thread number. If a request * is in service, just squashes the targets. * @param threadNum The thread to squash. */ @@ -196,7 +196,7 @@ class MSHRQueue { /** * Returns true if the pending list is not empty. - * @return True if there are outstanding pktuests. + * @return True if there are outstanding requests. */ bool havePending() const { @@ -213,8 +213,8 @@ class MSHRQueue { } /** - * Returns the pktuest at the head of the pendingList. - * @return The next pktuest to service. + * Returns the request at the head of the pendingList. + * @return The next request to service. */ PacketPtr getReq() const { diff --git a/src/mem/cache/tags/split.hh b/src/mem/cache/tags/split.hh index 748f6fb25..898d3c7a0 100644 --- a/src/mem/cache/tags/split.hh +++ b/src/mem/cache/tags/split.hh @@ -71,13 +71,13 @@ class Split : public BaseTags Addr blkMask; - /** Number of NIC pktuests that hit in the NIC partition */ + /** Number of NIC requests that hit in the NIC partition */ Stats::Scalar<> NR_NP_hits; - /** Number of NIC pktuests that hit in the CPU partition */ + /** Number of NIC requests that hit in the CPU partition */ Stats::Scalar<> NR_CP_hits; - /** Number of CPU pktuests that hit in the NIC partition */ + /** Number of CPU requests that hit in the NIC partition */ Stats::Scalar<> CR_NP_hits; - /** Number of CPU pktuests that hit in the CPU partition */ + /** Number of CPU requests that hit in the CPU partition */ Stats::Scalar<> CR_CP_hits; /** The number of nic replacements (i.e. misses) */ Stats::Scalar<> nic_repl; diff --git a/src/mem/cache/tags/split_blk.hh b/src/mem/cache/tags/split_blk.hh index 64d903579..f38516180 100644 --- a/src/mem/cache/tags/split_blk.hh +++ b/src/mem/cache/tags/split_blk.hh @@ -47,7 +47,7 @@ class SplitBlk : public CacheBlk { bool isTouched; /** Has this block been used after being brought in? (for LIFO partition) */ bool isUsed; - /** is this blk a NIC block? (i.e. pktuested by the NIC) */ + /** is this blk a NIC block? (i.e. requested by the NIC) */ bool isNIC; /** timestamp of the arrival of this block into the cache */ Tick ts; diff --git a/src/mem/packet.cc b/src/mem/packet.cc index fa8d82c46..a342af634 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -182,11 +182,11 @@ fixPacket(PacketPtr func, PacketPtr timing) if (funcStart >= timingStart) { memcpy(timing->getPtr<uint8_t>() + (funcStart - timingStart), func->getPtr<uint8_t>(), - funcStart - std::min(funcEnd, timingEnd)); + std::min(funcEnd, timingEnd) - funcStart); } else { // timingStart > funcStart memcpy(timing->getPtr<uint8_t>(), func->getPtr<uint8_t>() + (timingStart - funcStart), - timingStart - std::min(funcEnd, timingEnd)); + std::min(funcEnd, timingEnd) - timingStart); } // we always want to keep going with a write return true; diff --git a/src/mem/tport.cc b/src/mem/tport.cc index 55a461a8b..b9d5cbe4a 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -33,15 +33,16 @@ void SimpleTimingPort::recvFunctional(PacketPtr pkt) { - std::list<PacketPtr>::iterator i = transmitList.begin(); - std::list<PacketPtr>::iterator end = transmitList.end(); + std::list<std::pair<Tick,PacketPtr> >::iterator i = transmitList.begin(); + std::list<std::pair<Tick,PacketPtr> >::iterator end = transmitList.end(); + bool done = false; - while (i != end) { - PacketPtr target = *i; + while (i != end && !done) { + PacketPtr target = i->second; // If the target contains data, and it overlaps the // probed request, need to update data if (target->intersect(pkt)) - fixPacket(pkt, target); + done = fixPacket(pkt, target); } @@ -63,7 +64,7 @@ SimpleTimingPort::recvTiming(PacketPtr pkt) // turn packet around to go back to requester if response expected if (pkt->needsResponse()) { pkt->makeTimingResponse(); - sendTimingLater(pkt, latency); + sendTiming(pkt, latency); } else { if (pkt->cmd != Packet::UpgradeReq) @@ -78,14 +79,14 @@ SimpleTimingPort::recvTiming(PacketPtr pkt) void SimpleTimingPort::recvRetry() { - assert(outTiming > 0); assert(!transmitList.empty()); - if (sendTiming(transmitList.front())) { + if (Port::sendTiming(transmitList.front().second)) { transmitList.pop_front(); - outTiming--; DPRINTF(Bus, "No Longer waiting on retry\n"); - if (!transmitList.empty()) - sendTimingLater(transmitList.front(), 1); + if (!transmitList.empty()) { + Tick time = transmitList.front().first; + sendEvent.schedule(time <= curTick ? curTick+1 : time); + } } if (transmitList.empty() && drainEvent) { @@ -95,38 +96,43 @@ SimpleTimingPort::recvRetry() } void +SimpleTimingPort::sendTiming(PacketPtr pkt, Tick time) +{ + if (transmitList.empty()) { + assert(!sendEvent.scheduled()); + sendEvent.schedule(curTick+time); + } + transmitList.push_back(std::pair<Tick,PacketPtr>(time+curTick,pkt)); +} + +void SimpleTimingPort::SendEvent::process() { - assert(port->outTiming > 0); - if (!port->transmitList.empty() && port->transmitList.front() != packet) { - //We are not the head of the list - port->transmitList.push_back(packet); - } else if (port->sendTiming(packet)) { - // send successful - if (port->transmitList.size()) { - port->transmitList.pop_front(); - port->outTiming--; - if (!port->transmitList.empty()) - port->sendTimingLater(port->transmitList.front(), 1); + assert(port->transmitList.size()); + assert(port->transmitList.front().first <= curTick); + if (port->Port::sendTiming(port->transmitList.front().second)) { + //send successful, remove packet + port->transmitList.pop_front(); + if (!port->transmitList.empty()) { + Tick time = port->transmitList.front().first; + schedule(time <= curTick ? curTick+1 : time); } if (port->transmitList.empty() && port->drainEvent) { port->drainEvent->process(); port->drainEvent = NULL; } - } else { - // send unsuccessful (due to flow control). Will get retry - // callback later; save for then if not already - DPRINTF(Bus, "Waiting on retry\n"); - if (!(port->transmitList.front() == packet)) - port->transmitList.push_back(packet); + return; } + // send unsuccessful (due to flow control). Will get retry + // callback later; save for then if not already + DPRINTF(Bus, "Waiting on retry\n"); } unsigned int SimpleTimingPort::drain(Event *de) { - if (outTiming == 0 && transmitList.size() == 0) + if (transmitList.size() == 0) return 0; drainEvent = de; return 1; diff --git a/src/mem/tport.hh b/src/mem/tport.hh index fbe81c443..438ec56dc 100644 --- a/src/mem/tport.hh +++ b/src/mem/tport.hh @@ -60,23 +60,22 @@ class SimpleTimingPort : public Port protected: /** A list of outgoing timing response packets that haven't been * serviced yet. */ - std::list<PacketPtr> transmitList; + std::list<std::pair<Tick,PacketPtr> > transmitList; /** * This class is used to implemented sendTiming() with a delay. When - * a delay is requested a new event is created. When the event time - * expires it attempts to send the packet. If it cannot, the packet - * is pushed onto the transmit list to be sent when recvRetry() is - * called. */ + * a delay is requested a the event is scheduled if it isn't already. + * When the event time expires it attempts to send the packet. + * If it cannot, the packet sent when recvRetry() is called. + **/ class SendEvent : public Event { SimpleTimingPort *port; - PacketPtr packet; public: - SendEvent(SimpleTimingPort *p, PacketPtr pkt, Tick t) - : Event(&mainEventQueue), port(p), packet(pkt) - { setFlags(AutoDelete); schedule(curTick + t); } + SendEvent(SimpleTimingPort *p) + : Event(&mainEventQueue), port(p) + { } virtual void process(); @@ -84,19 +83,17 @@ class SimpleTimingPort : public Port { return "Future scheduled sendTiming event"; } }; - - /** Number of timing requests that are emulating the device timing before - * attempting to end up on the bus. - */ - int outTiming; + SendEvent sendEvent; /** If we need to drain, keep the drain event around until we're done * here.*/ Event *drainEvent; - /** Schedule a sendTiming() event to be called in the future. */ - void sendTimingLater(PacketPtr pkt, Tick time) - { outTiming++; new SendEvent(this, pkt, time); } + /** Schedule a sendTiming() event to be called in the future. + * @param pkt packet to send + * @param time increment from now (in ticks) to send packet + */ + void sendTiming(PacketPtr pkt, Tick time); /** This function is notification that the device should attempt to send a * packet again. */ @@ -118,7 +115,7 @@ class SimpleTimingPort : public Port public: SimpleTimingPort(std::string pname) - : Port(pname), outTiming(0), drainEvent(NULL) + : Port(pname), sendEvent(this), drainEvent(NULL) {} /** Hook for draining timing accesses from the system. The diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index 03e0508fb..d41fd5a61 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -150,7 +150,6 @@ def changeToAtomic(system): doDrain(system) print "Changing memory mode to atomic" system.changeTiming(cc_main.SimObject.Atomic) - resume(system) def changeToTiming(system): if not isinstance(system, objects.Root) and not isinstance(system, objects.System): @@ -159,7 +158,6 @@ def changeToTiming(system): doDrain(system) print "Changing memory mode to timing" system.changeTiming(cc_main.SimObject.Timing) - resume(system) def switchCpus(cpuList): print "switching cpus" @@ -190,7 +188,6 @@ def switchCpus(cpuList): cc_main.cleanupCountedDrain(drain_event) # Now all of the CPUs are ready to be switched out for old_cpu in old_cpus: - print "switching" old_cpu._ccObject.switchOut() index = 0 for new_cpu in new_cpus: diff --git a/src/python/m5/objects/Ethernet.py b/src/python/m5/objects/Ethernet.py index f17a6c888..a52e35511 100644 --- a/src/python/m5/objects/Ethernet.py +++ b/src/python/m5/objects/Ethernet.py @@ -71,7 +71,7 @@ class IGbE(PciDevice): class IGbEPciData(PciConfigData): VendorID = 0x8086 - DeviceID = 0x1026 + DeviceID = 0x1075 SubsystemID = 0x1008 SubsystemVendorID = 0x8086 Status = 0x0000 diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index 4eb0866a5..d913e159b 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -74,6 +74,8 @@ namespace AlphaPseudo if (!doQuiesce) return; + DPRINTF(Quiesce, "%s: quiesce()\n", tc->getCpuPtr()->name()); + tc->suspend(); if (tc->getKernelStats()) tc->getKernelStats()->quiesce(); |