/** * Copyright 2012 Tobias Gierke <tobias.gierke@code-sourcery.de> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.codesourcery.jasm16.emulator; import java.util.Collections; import java.util.List; import java.util.Random; import java.util.Set; import junit.framework.TestCase; import de.codesourcery.jasm16.Address; import de.codesourcery.jasm16.AddressRange; import de.codesourcery.jasm16.Size; import de.codesourcery.jasm16.emulator.memory.*; import de.codesourcery.jasm16.utils.Misc; public class MainMemoryTest extends TestCase implements IMemoryTypes { private MainMemory memory; @Override protected void setUp() throws Exception { super.setUp(); memory = new MainMemory(65536); } public static void main(String[] args) throws Exception { MainMemoryTest test = new MainMemoryTest(); test.setUp(); test.testRemappingSpeed(); } public void testMemoryAccessSpeed() { final int regionCount = 10; final int wordsPerRegion = 65536 / regionCount; int wordsLeft = 65536; int currentWord = 0; for ( int i = 0 ; i < regionCount ; i++ ) { int sizeInWords; if ( i == ( regionCount-1) ) { sizeInWords = wordsLeft; } else { sizeInWords = wordsPerRegion; } final AddressRange range = new AddressRange( Address.wordAddress( currentWord ) , Size.words( sizeInWords ) ); final MemoryRegion region = new MemoryRegion( "region #"+i, TYPE_RAM, range ); memory.mapRegion( region ); wordsLeft -= sizeInWords; currentWord += sizeInWords; } /* * Base value: 480 ms */ final Random rnd = new Random(0xdeadbeef); for ( int i = 0 ; i < 25 ; i++) { int sum = 0; rnd.setSeed( 0xdeadbeef ); long time = -System.currentTimeMillis(); for ( int j = 0 ; j < 10000000 ; j++ ) { final int adr = rnd.nextInt( 65536 ); sum += memory.read( adr ); } time += System.currentTimeMillis(); System.out.println("Time: "+time+" ms (sum: "+sum+")"); } } public void testRemappingSpeed() { AddressRange range1 = new AddressRange( Address.wordAddress( 0x8000 ) , Size.words( 384 ) ); MemoryRegion region1 = new MemoryRegion("region #1" , TYPE_RAM , range1 ); AddressRange range2 = new AddressRange( Address.wordAddress( 0x8180 ) , Size.words( 384 ) ); MemoryRegion region2 = new MemoryRegion("region #2" , TYPE_RAM , range2 ); MemoryRegion current = null; long delta = -System.currentTimeMillis(); long timeUnmap = 0; long timeMap= 0; for ( int i = 0 ; i < 500 ; i++ ) { if ( current == null ) { current = region1; } else { long time1 = -System.currentTimeMillis(); memory.unmapRegion( current ); time1 += System.currentTimeMillis(); timeUnmap += time1; if ( current == region1 ) { current = region2; } else { current = region1; } } long time2 = -System.currentTimeMillis(); memory.mapRegion( current ); time2 += System.currentTimeMillis(); timeMap += time2; } delta += System.currentTimeMillis(); System.out.println("Time "+delta+" millis."); System.out.println("MAP: Time "+timeMap+" millis."); System.out.println("UNMAP: Time "+timeUnmap+" millis."); } public void testMemoryRemapping() { /* DEBUG: Memory layout DEBUG: main memory - 0x0000 - 0x8000 ( 32768 words / 65536 bytes ) DEBUG: main memory - 0x8000 - 0x8180 ( 384 words / 768 bytes ) DEBUG: main memory - 0x8180 - 0x9000 ( 3712 words / 7424 bytes ) DEBUG: keyboard buffer (legacy) - 0x9000 - 0x9001 ( 1 words / 2 bytes ) DEBUG: main memory - 0x9001 - 0x010000 ( 28671 words / 57342 bytes ) */ AddressRange range1 = new AddressRange( Address.wordAddress( 0 ) , Address.wordAddress( 0x8000 ) ); MemoryRegion region1 = new MemoryRegion("region #1" , TYPE_RAM , range1 ); memory.mapRegion( region1 ); AddressRange range2 = new AddressRange( Address.wordAddress( 0x8000 ) , Address.wordAddress( 0x8180 ) ); MemoryRegion region2 = new MemoryRegion("region #2" , TYPE_RAM , range2 ); memory.mapRegion( region2 ); AddressRange range3 = new AddressRange( Address.wordAddress( 0x8180) , Address.wordAddress( 0x9000 ) ); MemoryRegion region3 = new MemoryRegion("region #3" , TYPE_RAM , range3 ); memory.mapRegion( region3 ); AddressRange range4 = new AddressRange( Address.wordAddress( 0x9000 ) , Address.wordAddress( 0x9001 ) ); MemoryRegion region4 = new MemoryRegion("region #4" , TYPE_RAM , range4 ); memory.mapRegion( region4 ); AddressRange range5 = new AddressRange( Address.wordAddress( 0x9001 ) , Address.wordAddress( 0x10000 ) ); MemoryRegion region5 = new MemoryRegion("region #5" , TYPE_RAM , range5 ); memory.mapRegion( region5 ); System.out.println("Memory layout"); memory.dumpMemoryLayout( new PrintStreamLogger( System.out ) ); fillMemoryRegion( memory, region1 , 0x1234 ); fillMemoryRegion( memory, region2 , 0x5678 ); fillMemoryRegion( memory, region3 , 0x90ab ); fillMemoryRegion( memory, region4 , 0xcdef ); fillMemoryRegion( memory, region5 , 0xbeef ); assertMemoryContains( region1 , 0x1234 ); assertMemoryContains( region2 , 0x5678 ); assertMemoryContains( region3 , 0x90ab ); assertMemoryContains( region4 , 0xcdef ); assertMemoryContains( region5 , 0xbeef ); AddressRange range6 = new AddressRange( Address.wordAddress( 0x4000 ) , Address.wordAddress( 0x4010 ) ); MemoryRegion region6 = new MemoryRegion("region #6" , TYPE_RAM , range6 ); memory.mapRegion( region6 ); assertMemoryContains( region6 , 0x1234 ); } private void fillMemoryRegion(IMemory memory , IMemoryRegion region , int value) { Address start = region.getAddressRange().getStartAddress(); int words = region.getSize().getSizeInWords(); for ( int i = 0 ; i < words ; i++ ) { memory.write( start , value); start = start.incrementByOne( false ); } } private void assertMemoryContains(IMemoryRegion region , int value) { assertMemoryContains( region, Address.wordAddress( 0 ) , region.getSize() , value ); } private void assertMemoryContains(IMemory region , Address start,Size size, int value) { Address current = start; int words = size.getSizeInWords(); for ( int i = 0 ; i < words ; i++ ) { if ( region.read( current ) != value ) { fail("Memory region "+region+" did not contain "+Misc.toHexString( value )+" at address "+Misc.toHexString( current ) ); } current = current.incrementByOne( false ); } } public void testRemappingOverNonMergableRegion() { AddressRange range1 = new AddressRange( Address.wordAddress( 0 ) , Address.wordAddress( 0x8000 ) ); AddressRange range2 = new AddressRange( Address.wordAddress( 0x8000 ) , Address.wordAddress( 0x8180 ) ); AddressRange range3 = new AddressRange( Address.wordAddress( 0x8180) , Address.wordAddress( 0x9000 ) ); MemoryRegion region1 = new MemoryRegion("region #1" , TYPE_RAM , range1 ); MemoryRegion region2 = new MemoryRegion("region #2" , TYPE_RAM , range2 ); MemoryRegion region3 = new MemoryRegion("region #3" , TYPE_RAM , range3 ); memory.mapRegion( region1 ); memory.mapRegion( region2 ); memory.mapRegion( region3 ); } public void testMemoryMerging() { AddressRange range1 = new AddressRange( Address.wordAddress( 0 ) , Address.wordAddress( 0x8000 ) ); MemoryRegion region1 = new MemoryRegion("region #1" , TYPE_RAM , range1 ); memory.mapRegion( region1 ); AddressRange range2 = new AddressRange( Address.wordAddress( 0x8000 ) , Address.wordAddress( 0x8180 ) ); MemoryRegion region2 = new MemoryRegion("region #2" , TYPE_RAM , range2 ); memory.mapRegion( region2 ); AddressRange range3 = new AddressRange( Address.wordAddress( 0x8180) , Address.wordAddress( 0x9000 ) ); MemoryRegion region3 = new MemoryRegion("region #3" , TYPE_RAM , range3 ); memory.mapRegion( region3 ); AddressRange range4 = new AddressRange( Address.wordAddress( 0x9000 ) , Address.wordAddress( 0x9001 ) ); MemoryRegion region4 = new MemoryRegion("region #4" , TYPE_RAM , range4 ); memory.mapRegion( region4 ); AddressRange range5 = new AddressRange( Address.wordAddress( 0x9001 ) , Address.wordAddress( 0x10000 ) ); MemoryRegion region5 = new MemoryRegion("region #5" , TYPE_RAM , range5 ); memory.mapRegion( region5 ); fillMemoryRegion( memory, region1 , 0x1234 ); fillMemoryRegion( memory, region2 , 0x5678 ); fillMemoryRegion( memory, region3 , 0x90ab ); fillMemoryRegion( memory, region4 , 0xcdef ); fillMemoryRegion( memory, region5 , 0xbeef ); assertMemoryContains( memory , region1.getAddressRange().getStartAddress() , region1.getSize() , 0x1234 ); assertMemoryContains( memory , region2.getAddressRange().getStartAddress() , region2.getSize() , 0x5678 ); assertMemoryContains( memory , region3.getAddressRange().getStartAddress() , region3.getSize() , 0x90ab ); assertMemoryContains( memory , region4.getAddressRange().getStartAddress() , region4.getSize() , 0xcdef ); assertMemoryContains( memory , region5.getAddressRange().getStartAddress() , region5.getSize() , 0xbeef ); memory.unmapRegion( region3 ); memory.unmapRegion( region5 ); memory.unmapRegion( region2 ); memory.unmapRegion( region1 ); memory.unmapRegion( region4 ); System.out.println("Memory layout"); memory.dumpMemoryLayout( new PrintStreamLogger( System.out ) ); assertMemoryContains( memory , region1.getAddressRange().getStartAddress() , region1.getSize() , 0x1234 ); assertMemoryContains( memory , region2.getAddressRange().getStartAddress() , region2.getSize() , 0x5678 ); assertMemoryContains( memory , region3.getAddressRange().getStartAddress() , region3.getSize() , 0x90ab ); assertMemoryContains( memory , region4.getAddressRange().getStartAddress() , region4.getSize() , 0xcdef ); assertMemoryContains( memory , region5.getAddressRange().getStartAddress() , region5.getSize() , 0xbeef ); } }