mem: Add DDR3 and LPDDR2 DRAM controller configurations

This patch moves the default DRAM parameters from the SimpleDRAM class
to two different subclasses, one for DDR3 and one for LPDDR2. More can
be added as we go forward.

The regressions that previously used the SimpleDRAM are now using
SimpleDDR3 as this is the most similar configuration.
This commit is contained in:
Andreas Hansson 2013-01-31 07:49:14 -05:00
parent eaa37e611f
commit c4898b15bc
7 changed files with 111 additions and 35 deletions

View file

@ -73,7 +73,7 @@ def makeLinuxAlphaSystem(mem_mode, mdesc = None):
# base address (including the PCI config space) # base address (including the PCI config space)
self.bridge = Bridge(delay='50ns', self.bridge = Bridge(delay='50ns',
ranges = [AddrRange(IO_address_space_base, Addr.max)]) ranges = [AddrRange(IO_address_space_base, Addr.max)])
self.physmem = SimpleDRAM(range = AddrRange(mdesc.mem())) self.physmem = SimpleDDR3(range = AddrRange(mdesc.mem()))
self.mem_ranges = [self.physmem.range] self.mem_ranges = [self.physmem.range]
self.bridge.master = self.iobus.slave self.bridge.master = self.iobus.slave
self.bridge.slave = self.membus.master self.bridge.slave = self.membus.master
@ -110,7 +110,7 @@ def makeLinuxAlphaRubySystem(mem_mode, mdesc = None):
ide = IdeController(disks=[Parent.disk0, Parent.disk2], ide = IdeController(disks=[Parent.disk0, Parent.disk2],
pci_func=0, pci_dev=0, pci_bus=0) pci_func=0, pci_dev=0, pci_bus=0)
physmem = SimpleDRAM(range = AddrRange(mdesc.mem())) physmem = SimpleDDR3(range = AddrRange(mdesc.mem()))
self = LinuxAlphaSystem(physmem = physmem) self = LinuxAlphaSystem(physmem = physmem)
self.mem_ranges = [self.physmem.range] self.mem_ranges = [self.physmem.range]
if not mdesc: if not mdesc:
@ -180,10 +180,10 @@ def makeSparcSystem(mem_mode, mdesc = None):
self.t1000 = T1000() self.t1000 = T1000()
self.t1000.attachOnChipIO(self.membus) self.t1000.attachOnChipIO(self.membus)
self.t1000.attachIO(self.iobus) self.t1000.attachIO(self.iobus)
self.physmem = SimpleDRAM(range = AddrRange(Addr('1MB'), size = '64MB'), self.physmem = SimpleDDR3(range = AddrRange(Addr('1MB'), size = '64MB'),
zero = True) zero = True)
self.physmem2 = SimpleDRAM(range = AddrRange(Addr('2GB'), size ='256MB'), self.physmem2 = SimpleDDR3(range = AddrRange(Addr('2GB'), size ='256MB'),
zero = True) zero = True)
self.mem_ranges = [self.physmem.range, self.physmem2.range] self.mem_ranges = [self.physmem.range, self.physmem2.range]
self.bridge.master = self.iobus.slave self.bridge.master = self.iobus.slave
self.bridge.slave = self.membus.master self.bridge.slave = self.membus.master
@ -274,8 +274,8 @@ def makeArmSystem(mem_mode, machine_type, mdesc = None, bare_metal=False):
if bare_metal: if bare_metal:
# EOT character on UART will end the simulation # EOT character on UART will end the simulation
self.realview.uart.end_on_eot = True self.realview.uart.end_on_eot = True
self.physmem = SimpleDRAM(range = AddrRange(Addr(mdesc.mem())), self.physmem = SimpleDDR3(range = AddrRange(Addr(mdesc.mem())),
zero = True) zero = True)
self.mem_ranges = [self.physmem.range] self.mem_ranges = [self.physmem.range]
else: else:
self.kernel = binary('vmlinux.arm.smp.fb.2.6.38.8') self.kernel = binary('vmlinux.arm.smp.fb.2.6.38.8')
@ -289,10 +289,10 @@ def makeArmSystem(mem_mode, machine_type, mdesc = None, bare_metal=False):
boot_flags = 'earlyprintk console=ttyAMA0 lpj=19988480 norandmaps ' + \ boot_flags = 'earlyprintk console=ttyAMA0 lpj=19988480 norandmaps ' + \
'rw loglevel=8 mem=%s root=/dev/sda1' % mdesc.mem() 'rw loglevel=8 mem=%s root=/dev/sda1' % mdesc.mem()
self.physmem = SimpleDRAM(range = self.physmem = SimpleDDR3(range =
AddrRange(self.realview.mem_start_addr, AddrRange(self.realview.mem_start_addr,
size = mdesc.mem()), size = mdesc.mem()),
conf_table_reported = True) conf_table_reported = True)
self.mem_ranges = [self.physmem.range] self.mem_ranges = [self.physmem.range]
self.realview.setupBootLoader(self.membus, self, binary) self.realview.setupBootLoader(self.membus, self, binary)
self.gic_cpu_addr = self.realview.gic.cpu_addr self.gic_cpu_addr = self.realview.gic.cpu_addr
@ -328,7 +328,7 @@ def makeLinuxMipsSystem(mem_mode, mdesc = None):
self.iobus = NoncoherentBus() self.iobus = NoncoherentBus()
self.membus = MemBus() self.membus = MemBus()
self.bridge = Bridge(delay='50ns') self.bridge = Bridge(delay='50ns')
self.physmem = SimpleDRAM(range = AddrRange('1GB')) self.physmem = SimpleDDR3(range = AddrRange('1GB'))
self.mem_ranges = [self.physmem.range] self.mem_ranges = [self.physmem.range]
self.bridge.master = self.iobus.slave self.bridge.master = self.iobus.slave
self.bridge.slave = self.membus.master self.bridge.slave = self.membus.master
@ -434,7 +434,7 @@ def makeX86System(mem_mode, numCPUs = 1, mdesc = None, self = None, Ruby = False
self.mem_mode = mem_mode self.mem_mode = mem_mode
# Physical memory # Physical memory
self.physmem = SimpleDRAM(range = AddrRange(mdesc.mem())) self.physmem = SimpleDDR3(range = AddrRange(mdesc.mem()))
self.mem_ranges = [self.physmem.range] self.mem_ranges = [self.physmem.range]
# Platform # Platform

View file

@ -63,11 +63,6 @@ class SimpleDRAM(AbstractMemory):
# bus in front of the controller for multiple ports # bus in front of the controller for multiple ports
port = SlavePort("Slave port") port = SlavePort("Slave port")
# the physical organisation of the DRAM
lines_per_rowbuffer = Param.Unsigned(64, "Row buffer size in cache lines")
ranks_per_channel = Param.Unsigned(2, "Number of ranks per channel")
banks_per_rank = Param.Unsigned(8, "Number of banks per rank")
# the basic configuration of the controller architecture # the basic configuration of the controller architecture
write_buffer_size = Param.Unsigned(32, "Number of read queue entries") write_buffer_size = Param.Unsigned(32, "Number of read queue entries")
read_buffer_size = Param.Unsigned(32, "Number of write queue entries") read_buffer_size = Param.Unsigned(32, "Number of write queue entries")
@ -77,21 +72,26 @@ class SimpleDRAM(AbstractMemory):
write_thresh_perc = Param.Percent(70, "Threshold to trigger writes") write_thresh_perc = Param.Percent(70, "Threshold to trigger writes")
# scheduler, address map and page policy # scheduler, address map and page policy
mem_sched_policy = Param.MemSched('fcfs', "Memory scheduling policy") mem_sched_policy = Param.MemSched('frfcfs', "Memory scheduling policy")
addr_mapping = Param.AddrMap('openmap', "Address mapping policy") addr_mapping = Param.AddrMap('openmap', "Address mapping policy")
page_policy = Param.PageManage('open', "Page closure management policy") page_policy = Param.PageManage('open', "Page closure management policy")
# the physical organisation of the DRAM
lines_per_rowbuffer = Param.Unsigned("Row buffer size in cache lines")
ranks_per_channel = Param.Unsigned("Number of ranks per channel")
banks_per_rank = Param.Unsigned("Number of banks per rank")
# timing behaviour and constraints - all in nanoseconds # timing behaviour and constraints - all in nanoseconds
# the amount of time in nanoseconds from issuing an activate command # the amount of time in nanoseconds from issuing an activate command
# to the data being available in the row buffer for a read/write # to the data being available in the row buffer for a read/write
tRCD = Param.Latency("14ns", "RAS to CAS delay") tRCD = Param.Latency("RAS to CAS delay")
# the time from issuing a read/write command to seeing the actual data # the time from issuing a read/write command to seeing the actual data
tCL = Param.Latency("14ns", "CAS latency") tCL = Param.Latency("CAS latency")
# minimum time between a precharge and subsequent activate # minimum time between a precharge and subsequent activate
tRP = Param.Latency("14ns", "Row precharge time") tRP = Param.Latency("Row precharge time")
# time to complete a burst transfer, typically the burst length # time to complete a burst transfer, typically the burst length
# divided by two due to the DDR bus, but by making it a parameter # divided by two due to the DDR bus, but by making it a parameter
@ -99,23 +99,22 @@ class SimpleDRAM(AbstractMemory):
# This parameter has to account for bus width and burst length. # This parameter has to account for bus width and burst length.
# Adjustment also necessary if cache line size is greater than # Adjustment also necessary if cache line size is greater than
# data size read/written by one full burst. # data size read/written by one full burst.
tBURST = Param.Latency("4ns", tBURST = Param.Latency("Burst duration (for DDR burst length / 2 cycles)")
"Burst duration (for DDR burst length / 2 cycles)")
# time taken to complete one refresh cycle (N rows in all banks) # time taken to complete one refresh cycle (N rows in all banks)
tRFC = Param.Latency("300ns", "Refresh cycle time") tRFC = Param.Latency("Refresh cycle time")
# refresh command interval, how often a "ref" command needs # refresh command interval, how often a "ref" command needs
# to be sent. It is 7.8 us for a 64ms refresh requirement # to be sent. It is 7.8 us for a 64ms refresh requirement
tREFI = Param.Latency("7.8us", "Refresh command interval") tREFI = Param.Latency("Refresh command interval")
# write-to-read turn around penalty, assumed same as read-to-write # write-to-read turn around penalty, assumed same as read-to-write
tWTR = Param.Latency("1ns", "Write to read switching time") tWTR = Param.Latency("Write to read switching time")
# time window in which a maximum number of activates are allowed # time window in which a maximum number of activates are allowed
# to take place, set to 0 to disable # to take place, set to 0 to disable
tXAW = Param.Latency("0ns", "X activation window") tXAW = Param.Latency("X activation window")
activation_limit = Param.Unsigned(4, "Max number of activates in window") activation_limit = Param.Unsigned("Max number of activates in window")
# Currently rolled into other params # Currently rolled into other params
###################################################################### ######################################################################
@ -127,3 +126,80 @@ class SimpleDRAM(AbstractMemory):
# tRC - assumed to be 4 * tRP # tRC - assumed to be 4 * tRP
# burst length for an access derived from peerBlockSize # burst length for an access derived from peerBlockSize
# High-level model of a single DDR3 x64 interface (one command and
# address bus), with default timings based on a DDR3-1600 4 Gbit part,
# which would amount to 4 Gbyte of memory in 8x8 or 8 GByte in 16x4
# configuration.
class SimpleDDR3(SimpleDRAM):
# Assuming 64 byte cache lines, use a 2kbyte page size, this
# depends on the memory density
lines_per_rowbuffer = 32
# Use two ranks
ranks_per_channel = 2
# DDR3 has 8 banks in all configurations
banks_per_rank = 8
# DDR3-1600 11-11-11
tRCD = '13.75ns'
tCL = '13.75ns'
tRP = '13.75ns'
# Assuming 64 byte cache lines, across an x64 (8x8 or 16x4)
# interface, translates to BL8, 4 clocks @ 800 MHz
tBURST = '5ns'
# DDR3, 4 Gb has a tRFC of 240 CK and tCK = 1.25 ns
tRFC = '300ns'
# DDR3, <=85C, half for >85C
tREFI = '7.8us'
# Greater of 4 CK or 7.5 ns, 4 CK @ 800 MHz = 5 ns
tWTR = '7.5ns'
# With a 2kbyte page size, DDR3-1600 lands around 40 ns
tXAW = '40ns'
activation_limit = 4
# High-level model of a single LPDDR2-S4 x64 interface (one
# command/address bus), with default timings based on a LPDDR2-1066
# 4Gbit part, which whould amount to 1 GByte of memory in 2x32 or
# 2GByte in 4x16 configuration.
class SimpleLPDDR2_S4(SimpleDRAM):
# Assuming 64 byte cache lines, use a 2kbyte page size, this
# depends on the memory density
lines_per_rowbuffer = 32
# Use two ranks
ranks_per_channel = 2
# LPDDR2-S4 has 8 banks in all configurations
banks_per_rank = 8
# Fixed at 15 ns
tRCD = '15ns'
# 8 CK read latency, 4 CK write latency @ 533 MHz, 1.876 ns cycle time
tCL = '15ns'
# Pre-charge one bank 15 ns and all banks 18 ns
tRP = '18ns'
# Assuming 64 byte cache lines, across a x64 interface (2x32 or
# 4x16), translates to BL8, 4 clocks @ 533 MHz
tBURST = '7.5ns'
# LPDDR2-S4, 4 Gb
tRFC = '130ns'
tREFI = '3.9us'
# Irrespective of speed grade, tWTR is 7.5 ns
tWTR = '7.5ns'
# Irrespective of size, tFAW is 50 ns
tXAW = '50ns'
activation_limit = 4

View file

@ -39,7 +39,7 @@ cpu.addTwoLevelCacheHierarchy(L1Cache(size = '128kB'),
cpu.clock = '2GHz' cpu.clock = '2GHz'
system = System(cpu = cpu, system = System(cpu = cpu,
physmem = SimpleDRAM(), physmem = SimpleDDR3(),
membus = CoherentBus(), membus = CoherentBus(),
mem_mode = "timing") mem_mode = "timing")
system.system_port = system.membus.slave system.system_port = system.membus.slave

View file

@ -52,7 +52,7 @@ cpu.addTwoLevelCacheHierarchy(L1Cache(size = '128kB'),
cpu.clock = '2GHz' cpu.clock = '2GHz'
system = System(cpu = cpu, system = System(cpu = cpu,
physmem = SimpleDRAM(), physmem = SimpleDDR3(),
membus = CoherentBus(), membus = CoherentBus(),
mem_mode = "timing") mem_mode = "timing")
system.system_port = system.membus.slave system.system_port = system.membus.slave

View file

@ -36,7 +36,7 @@ cpus = [ DerivO3CPU(cpu_id=i) for i in xrange(nb_cores) ]
# system simulated # system simulated
system = System(cpu = cpus, system = System(cpu = cpus,
physmem = SimpleDRAM(), physmem = SimpleDDR3(),
membus = CoherentBus(), membus = CoherentBus(),
mem_mode = "timing") mem_mode = "timing")

View file

@ -41,7 +41,7 @@ cpu.addTwoLevelCacheHierarchy(L1Cache(size = '128kB'),
cpu.clock = '2GHz' cpu.clock = '2GHz'
system = System(cpu = cpu, system = System(cpu = cpu,
physmem = SimpleDRAM(), physmem = SimpleDDR3(),
membus = CoherentBus(), membus = CoherentBus(),
mem_mode = "timing") mem_mode = "timing")
system.system_port = system.membus.slave system.system_port = system.membus.slave

View file

@ -48,7 +48,7 @@ require_sim_object("CommMonitor")
cpu = TrafficGen(config_file = "tests/quick/se/70.tgen/tgen-simple-dram.cfg") cpu = TrafficGen(config_file = "tests/quick/se/70.tgen/tgen-simple-dram.cfg")
# system simulated # system simulated
system = System(cpu = cpu, physmem = SimpleDRAM(), system = System(cpu = cpu, physmem = SimpleDDR3(),
membus = NoncoherentBus(clock="1GHz", width = 16)) membus = NoncoherentBus(clock="1GHz", width = 16))
# add a communication monitor # add a communication monitor