Ejemplo n.º 1
0
Archivo: Word.cs Proyecto: malyn/MFORTH
        /// <summary>
        /// Initializes a new instance of the Word class whose Name
        /// Field Address is located at "nfa" in the given ROM.
        /// </summary>
        /// <param name="rom">MFORTH ROM.</param>
        /// <param name="nfa">Name Field Address of the word.</param>
        public Word(ROM rom, int nfa)
        {
            // Store the NFA.
            this.NFA = nfa;

            // Get the name of the word.
            this.Name = GetWordName(rom, nfa);

            // Get the address of the next (previous) word in the
            // dictionary.
            this.NextWordAddr = rom.GetInt16(nfa + NFATOLFASZ);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// phashgen entry point.
        /// </summary>
        /// <param name="args">ROM path, symbol table path, output
        /// path.</param>
        public static void Main(string[] args)
        {
            // Load the ROM.
            var rom = new ROM(args[0]);

            // Load the symbol table.
            IDictionary<int, string> symbolTable = LoadSymbolTable(args[1]);

            // Open the output file.
            StreamWriter outFile = new StreamWriter(args[2], false, Encoding.ASCII);

            // Generate the hash table.
            Console.Write("Generating PHASH tables: ");
            PearsonHashFunction phf1, phf2;
            var hashTable = GenerateHashTable(rom, out phf1, out phf2);
            Console.WriteLine(" Done!");
            Console.WriteLine(
                "Total words: {0}; at first hash location: {1}; at second hash location: {2}",
                rom.NumWords,
                hashTable.NumValuesStoredAtFirstHash,
                hashTable.NumValuesStoredAtSecondHash);

            // Write out the mask value and auxilliary tables used to
            // construct the hash table.
            outFile.WriteLine(
                "PHASHMASK:  .EQU    0{0:X2}h",
                HashMask >> 8);

            outFile.WriteLine(
                "PHASHAUX1:  .ORG    0{0:X4}h",
                ROM.Size - (HashTableSize << 1) - (2 * PearsonHashFunction.AuxilliaryTableSize));
            WriteByteData(outFile, phf1.AuxilliaryTable);

            outFile.WriteLine(
                "PHASHAUX2:  .ORG    0{0:X4}h",
                ROM.Size - (HashTableSize << 1) - PearsonHashFunction.AuxilliaryTableSize);
            WriteByteData(outFile, phf2.AuxilliaryTable);

            // Write out the hash table.
            outFile.WriteLine(
                "PHASHTAB:   .ORG    0{0:X4}h",
                ROM.Size - (HashTableSize << 1));
            WriteHashTable(outFile, hashTable, symbolTable);

            // Close the output file; we're done!
            outFile.Close();
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Generate the MFORTH hash table.
        /// </summary>
        /// <param name="rom">MFORTH ROM.</param>
        /// <param name="phf1">Upon return, will contain the first
        /// PearsonHashFunction used by the hash table.</param>
        /// <param name="phf2">Upon return, will contain the second
        /// PearsonHashFunction used by the hash table.</param>
        /// <returns>The MFORTH hash table.</returns>
        private static CuckooHashTable<Word> GenerateHashTable(ROM rom, out PearsonHashFunction phf1, out PearsonHashFunction phf2)
        {
            // Initialize our random number generator.
            var random = new Random(HashTableRandomSeed);

            // Initialize our hash functions and the hash table.
            var hashFunc1 = phf1 = new PearsonHashFunction(random);
            var hashFunc2 = phf2 = new PearsonHashFunction(random);
            var hashTable = new CuckooHashTable<Word>(
                (w) => HashName(w.Name, hashFunc1, hashFunc2, HashMask),
                (w) => HashName(w.Name, hashFunc2, hashFunc1, HashMask));

            // Generate the hash table.
            #if FINDING_OPTIMAL_HASH_SEED
            int minValuesAtSecondLocation = int.MaxValue;
            #endif
            for (;;)
            {
            #if !FINDING_OPTIMAL_HASH_SEED
                // Display a progress dot.
                Console.Write(".");
            #endif

                // Add all of the words to our hash table; assume that
                // we will be successful.
                bool haveCompleteTable = true;
                foreach (var word in rom.Words)
                {
                    if (!hashTable.TryAddValue(word))
                    {
                        haveCompleteTable = false;
                        break;
                    }
                }

            #if !FINDING_OPTIMAL_HASH_SEED
                // We're done if all of the words were added to the
                // table.
                if (haveCompleteTable)
                {
                    break;
                }

                // We failed to generate a complete hash table; shuffle
                // the hash functions, clear the table, and try again.
                phf1.ShuffleAuxilliaryTable(random);
                phf2.ShuffleAuxilliaryTable(random);
                hashTable.Clear();
            #else
                // Print out the results if this seed produced better
                // results than the previous best seed.
                if (haveCompleteTable
                    && hashTable.NumValuesStoredAtSecondHash < minValuesAtSecondLocation)
                {
                    Console.WriteLine(
                        "Seed: {0}; 1st: {1}; 2nd: {2}",
                        HashTableRandomSeed,
                        hashTable.NumValuesStoredAtFirstHash,
                        hashTable.NumValuesStoredAtSecondHash);
                    minValuesAtSecondLocation = hashTable.NumValuesStoredAtSecondHash;
                }

                // Generate a new seed and re-create all of the hash
                // functions and tables.
                random = new Random(++HashTableRandomSeed);
                hashFunc1 = phf1 = new PearsonHashFunction(random);
                hashFunc2 = phf2 = new PearsonHashFunction(random);
                hashTable = new CuckooHashTable<Word>(
                    (w) => HashName(w.Name, hashFunc1, hashFunc2, HashMask),
                    (w) => HashName(w.Name, hashFunc2, hashFunc1, HashMask));
            #endif
            }

            // Ensure that all of the words in the ROM were added to the
            // hash table.
            if (rom.NumWords != hashTable.Count)
            {
                throw new InvalidDataException(
                    string.Format(
                        "Hash table only has {0} words; expected {1} words.",
                        hashTable.Count,
                        rom.NumWords));
            }

            // Return the hash table.
            return hashTable;
        }
Ejemplo n.º 4
0
Archivo: Word.cs Proyecto: malyn/MFORTH
        /// <summary>
        /// Gets the name of the word whose NFA is at the given address.
        /// </summary>
        /// <param name="rom">MFORTH ROM.</param>
        /// <param name="nfa">Name Field Address of the start of the
        /// name.</param>
        /// <returns>The name of the word.</returns>
        private static string GetWordName(ROM rom, int nfa)
        {
            // Get the length of the word's name from the byte at the
            // NFA.
            int wordLen = rom.GetInt8(nfa) & 0x3f;

            // Read the bytes in the word's name.  Ignore the length for
            // now and just use the end-of-name flag to determine when
            // to stop reading bytes.
            var word = new StringBuilder();
            for (int romOffset = nfa - 1;; romOffset--)
            {
                byte c = rom.GetInt8(romOffset);
                word.Append(Encoding.ASCII.GetString(new byte[] { (byte)(c & 0x7F) }));
                if ((c & 0x80) != 0)
                {
                    break;
                }
            }

            // Ensure that the decoded name is the correct length.
            if (word.Length != wordLen)
            {
                throw new InvalidDataException(
                    string.Format(
                        "Word '{0}' has NFA with incorrect length {1}.",
                        word,
                        wordLen));
            }

            // Return the name.
            return word.ToString();
        }