diff --git a/configs/common/FSConfig.py b/configs/common/FSConfig.py index eb0730ffa..fb3a5408f 100644 --- a/configs/common/FSConfig.py +++ b/configs/common/FSConfig.py @@ -73,7 +73,7 @@ def makeLinuxAlphaSystem(mem_mode, mdesc = None): # base address (including the PCI config space) self.bridge = Bridge(delay='50ns', 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.bridge.master = self.iobus.slave self.bridge.slave = self.membus.master @@ -110,7 +110,7 @@ def makeLinuxAlphaRubySystem(mem_mode, mdesc = None): ide = IdeController(disks=[Parent.disk0, Parent.disk2], 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.mem_ranges = [self.physmem.range] if not mdesc: @@ -180,10 +180,10 @@ def makeSparcSystem(mem_mode, mdesc = None): self.t1000 = T1000() self.t1000.attachOnChipIO(self.membus) self.t1000.attachIO(self.iobus) - self.physmem = SimpleDRAM(range = AddrRange(Addr('1MB'), size = '64MB'), - zero = True) - self.physmem2 = SimpleDRAM(range = AddrRange(Addr('2GB'), size ='256MB'), - zero = True) + self.physmem = SimpleDDR3(range = AddrRange(Addr('1MB'), size = '64MB'), + zero = True) + self.physmem2 = SimpleDDR3(range = AddrRange(Addr('2GB'), size ='256MB'), + zero = True) self.mem_ranges = [self.physmem.range, self.physmem2.range] self.bridge.master = self.iobus.slave self.bridge.slave = self.membus.master @@ -274,8 +274,8 @@ def makeArmSystem(mem_mode, machine_type, mdesc = None, bare_metal=False): if bare_metal: # EOT character on UART will end the simulation self.realview.uart.end_on_eot = True - self.physmem = SimpleDRAM(range = AddrRange(Addr(mdesc.mem())), - zero = True) + self.physmem = SimpleDDR3(range = AddrRange(Addr(mdesc.mem())), + zero = True) self.mem_ranges = [self.physmem.range] else: 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 ' + \ 'rw loglevel=8 mem=%s root=/dev/sda1' % mdesc.mem() - self.physmem = SimpleDRAM(range = - AddrRange(self.realview.mem_start_addr, - size = mdesc.mem()), - conf_table_reported = True) + self.physmem = SimpleDDR3(range = + AddrRange(self.realview.mem_start_addr, + size = mdesc.mem()), + conf_table_reported = True) self.mem_ranges = [self.physmem.range] self.realview.setupBootLoader(self.membus, self, binary) self.gic_cpu_addr = self.realview.gic.cpu_addr @@ -328,7 +328,7 @@ def makeLinuxMipsSystem(mem_mode, mdesc = None): self.iobus = NoncoherentBus() self.membus = MemBus() self.bridge = Bridge(delay='50ns') - self.physmem = SimpleDRAM(range = AddrRange('1GB')) + self.physmem = SimpleDDR3(range = AddrRange('1GB')) self.mem_ranges = [self.physmem.range] self.bridge.master = self.iobus.slave 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 # Physical memory - self.physmem = SimpleDRAM(range = AddrRange(mdesc.mem())) + self.physmem = SimpleDDR3(range = AddrRange(mdesc.mem())) self.mem_ranges = [self.physmem.range] # Platform diff --git a/src/mem/SimpleDRAM.py b/src/mem/SimpleDRAM.py index 83eaac611..41bad9356 100644 --- a/src/mem/SimpleDRAM.py +++ b/src/mem/SimpleDRAM.py @@ -63,11 +63,6 @@ class SimpleDRAM(AbstractMemory): # bus in front of the controller for multiple ports 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 write_buffer_size = Param.Unsigned(32, "Number of read 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") # 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") 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 # the amount of time in nanoseconds from issuing an activate command # 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 - tCL = Param.Latency("14ns", "CAS latency") + tCL = Param.Latency("CAS latency") # 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 # 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. # Adjustment also necessary if cache line size is greater than # data size read/written by one full burst. - tBURST = Param.Latency("4ns", - "Burst duration (for DDR burst length / 2 cycles)") + tBURST = Param.Latency("Burst duration (for DDR burst length / 2 cycles)") # 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 # 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 - 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 # to take place, set to 0 to disable - tXAW = Param.Latency("0ns", "X activation window") - activation_limit = Param.Unsigned(4, "Max number of activates in window") + tXAW = Param.Latency("X activation window") + activation_limit = Param.Unsigned("Max number of activates in window") # Currently rolled into other params ###################################################################### @@ -127,3 +126,80 @@ class SimpleDRAM(AbstractMemory): # tRC - assumed to be 4 * tRP # 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 diff --git a/tests/configs/inorder-timing.py b/tests/configs/inorder-timing.py index a92c61ba1..77c4f3d18 100644 --- a/tests/configs/inorder-timing.py +++ b/tests/configs/inorder-timing.py @@ -39,7 +39,7 @@ cpu.addTwoLevelCacheHierarchy(L1Cache(size = '128kB'), cpu.clock = '2GHz' system = System(cpu = cpu, - physmem = SimpleDRAM(), + physmem = SimpleDDR3(), membus = CoherentBus(), mem_mode = "timing") system.system_port = system.membus.slave diff --git a/tests/configs/o3-timing-checker.py b/tests/configs/o3-timing-checker.py index a33a2ac06..cd15cf66b 100644 --- a/tests/configs/o3-timing-checker.py +++ b/tests/configs/o3-timing-checker.py @@ -52,7 +52,7 @@ cpu.addTwoLevelCacheHierarchy(L1Cache(size = '128kB'), cpu.clock = '2GHz' system = System(cpu = cpu, - physmem = SimpleDRAM(), + physmem = SimpleDDR3(), membus = CoherentBus(), mem_mode = "timing") system.system_port = system.membus.slave diff --git a/tests/configs/o3-timing-mp.py b/tests/configs/o3-timing-mp.py index c3a4929bb..59f91a392 100644 --- a/tests/configs/o3-timing-mp.py +++ b/tests/configs/o3-timing-mp.py @@ -36,7 +36,7 @@ cpus = [ DerivO3CPU(cpu_id=i) for i in xrange(nb_cores) ] # system simulated system = System(cpu = cpus, - physmem = SimpleDRAM(), + physmem = SimpleDDR3(), membus = CoherentBus(), mem_mode = "timing") diff --git a/tests/configs/o3-timing.py b/tests/configs/o3-timing.py index 474d13902..8c3c9abe7 100644 --- a/tests/configs/o3-timing.py +++ b/tests/configs/o3-timing.py @@ -41,7 +41,7 @@ cpu.addTwoLevelCacheHierarchy(L1Cache(size = '128kB'), cpu.clock = '2GHz' system = System(cpu = cpu, - physmem = SimpleDRAM(), + physmem = SimpleDDR3(), membus = CoherentBus(), mem_mode = "timing") system.system_port = system.membus.slave diff --git a/tests/configs/tgen-simple-dram.py b/tests/configs/tgen-simple-dram.py index 0e9edc171..19eb15933 100644 --- a/tests/configs/tgen-simple-dram.py +++ b/tests/configs/tgen-simple-dram.py @@ -48,7 +48,7 @@ require_sim_object("CommMonitor") cpu = TrafficGen(config_file = "tests/quick/se/70.tgen/tgen-simple-dram.cfg") # system simulated -system = System(cpu = cpu, physmem = SimpleDRAM(), +system = System(cpu = cpu, physmem = SimpleDDR3(), membus = NoncoherentBus(clock="1GHz", width = 16)) # add a communication monitor