From: Daniel Kirschten Date: Mon, 16 Sep 2019 07:22:09 +0000 (+0200) Subject: Merge branch 'cont-integr-2' into 'development' X-Git-Url: https://mograsim.net/gitweb/?p=Mograsim.git;a=commitdiff_plain;h=58babf45ae7d259a296656451d796dbe601377a4 Merge branch 'cont-integr-2' into 'development' Switch to automatic build and test See merge request lrr-tum/students/eragp-misim-2019!1 --- 58babf45ae7d259a296656451d796dbe601377a4 diff --cc plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/CoreWordAddressableMemory.java index 00000000,ca557a6b..40abba9f mode 000000,100644..100644 --- a/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/CoreWordAddressableMemory.java +++ b/plugins/net.mograsim.machine/src/net/mograsim/machine/standard/memory/CoreWordAddressableMemory.java @@@ -1,0 -1,94 +1,94 @@@ + package net.mograsim.machine.standard.memory; + + import java.util.List; + + import net.mograsim.logic.core.components.BasicCoreComponent; + import net.mograsim.logic.core.timeline.Timeline; + import net.mograsim.logic.core.timeline.TimelineEventHandler; + import net.mograsim.logic.core.types.Bit; + import net.mograsim.logic.core.types.BitVector; + import net.mograsim.logic.core.wires.CoreWire.ReadEnd; + import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd; + import net.mograsim.machine.MainMemory; + import net.mograsim.machine.MainMemoryDefinition; + + /** + * A memory component that only allows access to words of a specific width + */ + public class CoreWordAddressableMemory extends BasicCoreComponent + { + private final MainMemory memory; + private final static Bit read = Bit.ONE; + + private ReadWriteEnd data; + private ReadEnd rWBit, address; + + /** + * @param data The bits of this ReadEnd are the value that is written to/read from memory; The bit width of this wire is the width of + * a memory word + * @param rWBit The value of the 0th bit dictates the mode: 0: Write, 1: Read + * @param address The bits of this ReadEnd address the memory cell to read/write + */ + public CoreWordAddressableMemory(Timeline timeline, int processTime, MainMemory memory, ReadWriteEnd data, ReadEnd rWBit, + ReadEnd address) + { + super(timeline, processTime); + MainMemoryDefinition definition = memory.getDefinition(); + if (data.width() != definition.getCellWidth()) + throw new IllegalArgumentException( + String.format("Bit width of data wire does not match main memory definition. Expected: %d Actual: %d", + definition.getCellWidth(), data.width())); + if (rWBit.width() != 1) + throw new IllegalArgumentException( + String.format("Bit width of read/write mode select wire is unexpected. Expected: 1 Actual: %d", rWBit.width())); + if (address.width() != definition.getMemoryAddressBits()) + throw new IllegalArgumentException( + String.format("Bit width of address wire does not match main memory definition. Expected: %d Actual: %d", + definition.getMemoryAddressBits(), address.width())); + this.memory = memory; + this.data = data; + this.rWBit = rWBit; + this.address = address; + memory.registerObserver(a -> update()); + data.registerObserver(this); + rWBit.registerObserver(this); + address.registerObserver(this); + } + + @Override + protected TimelineEventHandler compute() + { + if (!address.getValues().isBinary()) + { + if (read.equals(rWBit.getValue())) + return e -> data.feedSignals(Bit.U.toVector(data.width()));// TODO don't always feed U, but decide to feed X or U. + return e -> data.clearSignals(); + } + long addressed = address.getValues().getUnsignedValueLong(); + if (read.equals(rWBit.getValue())) + { + BitVector storedData = memory.getCell(addressed); + return e -> data.feedSignals(storedData); + } + BitVector transData = data.getValues(); - if (transData.equals(memory.getCell(addressed))) - return null; ++ boolean isNewData = !transData.equals(memory.getCell(addressed)); + return e -> + { + data.clearSignals(); - memory.setCell(addressed, transData); ++ if (isNewData) ++ memory.setCell(addressed, transData); + }; + } + + @Override + public List getAllInputs() + { + return List.of(data, rWBit, address); + } + + @Override + public List getAllOutputs() + { + return List.of(data); + } + } diff --cc tests/net.mograsim.machine.tests/src/net/mograsim/machine/standard/memory/WordAddressableMemoryTest.java index 00000000,9d38b894..ae8e8153 mode 000000,100644..100644 --- a/tests/net.mograsim.machine.tests/src/net/mograsim/machine/standard/memory/WordAddressableMemoryTest.java +++ b/tests/net.mograsim.machine.tests/src/net/mograsim/machine/standard/memory/WordAddressableMemoryTest.java @@@ -1,0 -1,64 +1,70 @@@ + package net.mograsim.machine.standard.memory; + + import static org.junit.jupiter.api.Assertions.assertEquals; + + import java.math.BigInteger; + import java.util.Random; ++import java.util.stream.LongStream; + -import org.junit.jupiter.api.Test; ++import org.junit.jupiter.params.ParameterizedTest; ++import org.junit.jupiter.params.provider.MethodSource; + + import net.mograsim.logic.core.timeline.Timeline; + import net.mograsim.logic.core.types.Bit; + import net.mograsim.logic.core.types.BitVector; + import net.mograsim.logic.core.wires.CoreWire; + import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd; + import net.mograsim.machine.MainMemoryDefinition; + + class WordAddressableMemoryTest + { + + private Timeline t = new Timeline(10); + - @Test - public void wordAddressableMemoryLargeTest() ++ @ParameterizedTest(name = "seed = {0}") ++ @MethodSource("seedsForRandom") ++ public void wordAddressableMemoryLargeTest(long seed) + { + CoreWire rW = new CoreWire(t, 1, 2); + CoreWire data = new CoreWire(t, 16, 2); + CoreWire address = new CoreWire(t, 64, 2); + ReadWriteEnd rWI = rW.createReadWriteEnd(); + ReadWriteEnd dataI = data.createReadWriteEnd(); + ReadWriteEnd addressI = address.createReadWriteEnd(); + + @SuppressWarnings("unused") + CoreWordAddressableMemory memory = new CoreWordAddressableMemory(t, 4, + new WordAddressableMemory(MainMemoryDefinition.create(64, 16, 4096L, Long.MAX_VALUE)), data.createReadWriteEnd(), + rW.createReadOnlyEnd(), address.createReadOnlyEnd()); + - Random r = new Random(); ++ Random r = new Random(seed); + for (long j = 1; j > 0; j *= 2) + { - for (int i = 0; i < 50; i++) ++ for (int i = 0; i < 100; i++) + { - String sAddress = String.format("%64s", BigInteger.valueOf(4096 + i + j).toString(2)).replace(' ', '0'); - BitVector bAddress = BitVector.parse(sAddress); ++ BitVector bAddress = BitVector.from(4096 + i + j, 64); + addressI.feedSignals(bAddress); + t.executeAll(); + String random = BigInteger.valueOf(Math.abs(r.nextInt())).toString(5); + random = random.substring(Integer.max(0, random.length() - 16)); + random = String.format("%16s", random).replace(' ', '0'); + random = random.replace('2', 'X').replace('3', 'Z').replace('4', 'U'); + BitVector vector = BitVector.parse(random); + dataI.feedSignals(vector); + rWI.feedSignals(Bit.ZERO); + t.executeAll(); + rWI.feedSignals(Bit.ONE); + t.executeAll(); + dataI.clearSignals(); + t.executeAll(); + - assertEquals(dataI.getValues(), vector); ++ assertEquals(vector, dataI.getValues(), "seed=" + seed + ", j=" + j + ", i=" + i); + } + } + } + ++ public static LongStream seedsForRandom() ++ { ++ return LongStream.range(0, 20); ++ } + }