#include "xmalloc.h"
/* sim65 */
+#include "cfgdata.h"
#include "chipdata.h"
#include "chiplib.h"
#include "error.h"
+static Chip* FindChip (const char* Name)
+/* Find a chip by name. Returns the Chip data structure or NULL if the chip
+ * could not be found.
+ */
+{
+ unsigned I;
+
+ /* ## We do a linear search for now */
+ for (I = 0; I < CollCount (&Chips); ++I) {
+
+ /* Get the chip at this position */
+ Chip* C = CollAt (&Chips, I);
+
+ /* Compare the name */
+ if (strcmp (Name, C->Data->ChipName) == 0) {
+ /* Found */
+ return C;
+ }
+ }
+
+ /* Not found */
+ return 0;
+}
+
+
+
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
-ChipInstance* NewChipInstance (unsigned long Addr, unsigned Size)
-/* Allocate a new chip instance for the chip. */
+ChipInstance* NewChipInstance (const char* ChipName, unsigned Addr,
+ unsigned Size, const Collection* Attributes)
{
- /* Allocate a new ChipInstance structure */
- ChipInstance* Instance = xmalloc (sizeof (*Instance));
-
- /* Initialize the fields */
- Instance->C = 0;
- Instance->Addr = Addr;
- Instance->Size = Size;
- Instance->InstanceData = 0;
-
- /* Return the new struct */
- return Instance;
-}
-
+ ChipInstance* CI;
+ /* Find the chip with the given name */
+ Chip* C = FindChip (ChipName);
+ if (C == 0) {
+ Error ("No chip `%s' found for address $%06X", ChipName, Addr);
+ }
-static Chip* FindChip (const char* Name)
-/* Find a chip by name. Returns the Chip data structure or NULL if the chip
- * could not be found.
- */
-{
- unsigned I;
-
- /* ## We do a linear search for now */
- for (I = 0; I < CollCount (&Chips); ++I) {
+ /* Allocate a new ChipInstance structure */
+ CI = xmalloc (sizeof (*CI));
- /* Get the chip at this position */
- Chip* C = CollAt (&Chips, I);
+ /* Initialize the fields */
+ CI->C = C;
+ CI->Addr = Addr;
+ CI->Size = Size;
+ CI->Data = C->Data->InitInstance (Addr, Size,
+ (const CfgData**) Attributes->Items,
+ CollCount (Attributes));
- /* Compare the name */
- if (strcmp (Name, C->Data->ChipName) == 0) {
- /* Found */
- return C;
- }
- }
+ /* Assign the chip instance to the chip */
+ CollAppend (&C->Instances, CI);
- /* Not found */
- return 0;
+ /* Return the new instance struct */
+ return CI;
}
-void InitChipInstance (ChipInstance* CI, const char* ChipName,
- const struct CfgData** Data, unsigned Count)
-/* Initialize the given chip instance. Assign it to the chip named ChipName,
- * and call the init function of the chip passing the given config data.
- */
+ChipInstance* MirrorChipInstance (const ChipInstance* Orig, unsigned Addr)
+/* Generate a chip instance mirror and return it. */
{
- /* Find the chip with the given name */
- Chip* C = FindChip (ChipName);
- if (C == 0) {
- Error ("No chip `%s' found for address $%6lX", ChipName, CI->Addr);
- }
+ /* Allocate a new ChipInstance structure */
+ ChipInstance* CI = xmalloc (sizeof (*CI));
- /* Call the initialization function */
- CI->InstanceData = C->Data->InitInstance (CI->Addr, CI->Size, Data, Count);
+ /* Initialize the fields */
+ CI->C = Orig->C;
+ CI->Addr = Addr;
+ CI->Size = Orig->Size;
+ CI->Data = Orig->Data;
/* Assign the chip instance to the chip */
- CI->C = C;
- CollAppend (&C->Instances, CI);
+ CollAppend (&CI->C->Instances, CI);
+
+ /* Return the new instance struct */
+ return CI;
}
/* One instance of a chip */
struct ChipInstance {
- Chip* C; /* Pointer to corresponding chip */
- unsigned long Addr; /* Start address of range */
- unsigned Size; /* Size of range */
- void* InstanceData; /* Chip instance data */
+ Chip* C; /* Pointer to corresponding chip */
+ unsigned Addr; /* Start address of range */
+ unsigned Size; /* Size of range */
+ void* Data; /* Chip instance data */
};
/* Chip structure */
Chip* NewChip (struct ChipLibrary* Library, const ChipData* Data);
/* Allocate a new chip structure, initialize and return it */
-ChipInstance* NewChipInstance (unsigned long Addr, unsigned Size);
+ChipInstance* NewChipInstance (const char* ChipName, unsigned Addr,
+ unsigned Size, const Collection* Attributes);
/* Allocate a new chip instance for the chip. */
-void InitChipInstance (ChipInstance* CI, const char* ChipName,
- const struct CfgData** Data, unsigned Count);
-/* Initialize the given chip instance. Assign it to the chip named ChipName,
- * and call the init function of the chip passing the given config data.
- */
+ChipInstance* MirrorChipInstance (const ChipInstance* Orig, unsigned Addr);
+/* Generate a chip instance mirror and return it. */
void SortChips (void);
/* Sort all chips by name. Called after loading */
#include "chip.h"
#include "error.h"
#include "global.h"
+#include "memory.h"
#include "scanner.h"
#include "config.h"
/* One memory location */
typedef struct Location Location;
struct Location {
- unsigned long Start; /* Start of memory location */
- unsigned long End; /* End memory location */
- Collection Attributes; /* Attributes given */
- unsigned Line; /* Line in config file */
- unsigned Col; /* Column in config file */
+ unsigned Start; /* Start of memory location */
+ unsigned End; /* End memory location */
+ Collection Attributes; /* Attributes given */
+ unsigned Line; /* Line in config file */
+ unsigned Col; /* Column in config file */
};
CfgData* D = xmalloc (sizeof (CfgData) + AttrLen);
/* Initialize the fields */
- D->Type = CfgDataInvalid;
+ D->Type = CfgDataInvalid;
D->Line = CfgErrorLine;
D->Col = CfgErrorCol;
memcpy (D->Attr, CfgSVal, AttrLen+1);
+static void FreeCfgData (CfgData* D)
+/* Free a config data structure */
+{
+ if (D->Type == CfgDataString) {
+ /* Free the string value */
+ xfree (D->V.SVal);
+ }
+ /* Free the structure */
+ xfree (D);
+}
+
+
+
+static void CfgDataCheckType (const CfgData* D, unsigned Type)
+/* Check the config data type */
+{
+ if (D->Type != Type) {
+ Error ("%s(%u): Attribute `%s' has invalid type",
+ CfgGetName (), D->Line, D->Attr);
+ }
+}
+
+
+
/*****************************************************************************/
/* struct Location */
/*****************************************************************************/
-static const CfgData* LocationFindAttr (const Location* L, const char* AttrName)
-/* Find the attribute with the given name and return it. Return NULL if the
- * attribute was not found.
+static int LocationFindAttr (const Location* L, const char* AttrName)
+/* Find the attribute with the given name and return its index. Return -1 if
+ * the attribute was not found.
*/
{
unsigned I;
/* Compare the name */
if (StrCaseCmp (D->Attr, AttrName) == 0) {
/* Found */
- return D;
+ return I;
}
}
/* Not found */
- return 0;
+ return -1;
}
-static int LocationIsMirror (const Location* L)
-/* Return true if the given location is a mirror of another one. */
+static int LocationGetAttr (const Location* L, const char* AttrName)
+/* Find the attribute with the given name and return it. Call Error() if the
+ * attribute was not found.
+ */
{
- /* Find the "mirror" attribute */
- return (LocationFindAttr (L, "mirror") != 0);
+ int I = LocationFindAttr (L, AttrName);
+ if (I < 0) {
+ Error ("%s(%u): Attribute `%s' missing", CfgGetName(), L->Line, AttrName);
+ }
+ return I;
}
-/*****************************************************************************/
-/* Code */
-/*****************************************************************************/
-
-
-
-static void FlagAttr (unsigned* Flags, unsigned Mask, const char* Name)
-/* Check if the item is already defined. Print an error if so. If not, set
- * the marker that we have a definition now.
- */
+static int LocationIsMirror (const Location* L)
+/* Return true if the given location is a mirror of another one. */
{
- if (*Flags & Mask) {
- CfgError ("%s is already defined", Name);
- }
- *Flags |= Mask;
+ /* Find the "mirror" attribute */
+ return (LocationFindAttr (L, "mirror") >= 0);
}
-static void AttrCheck (unsigned Attr, unsigned Mask, const char* Name)
-/* Check that a mandatory attribute was given */
-{
- if ((Attr & Mask) == 0) {
- CfgError ("%s attribute is missing", Name);
- }
-}
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
if (LocationIsMirror (L)) {
const CfgData* D;
if (CollCount (&L->Attributes) > 1) {
- Error ("%s(%u): Location at address $%06lX is a mirror "
+ Error ("%s(%u): Location at address $%06X is a mirror "
"but has attributes", CfgGetName(), L->Line, L->Start);
}
D = CollConstAt (&L->Attributes, 0);
- if (D->Type != CfgDataNumber) {
- Error ("%s(%u): Mirror attribute is not an integer",
- CfgGetName (), L->Line);
- }
+ CfgDataCheckType (D, CfgDataNumber);
}
/* Remember this entry */
Last = L;
}
+
+ /* Now create the chip instances. Since we can only mirror existing chips,
+ * we will first create all real chips and the mirrors in a second run.
+ */
+ for (I = 0; I < CollCount (&Locations); ++I) {
+
+ int Index;
+ CfgData* D;
+ unsigned Range; /* Address range for this chip */
+ ChipInstance* CI;
+
+ /* Get this location */
+ Location* L = CollAtUnchecked (&Locations, I);
+
+ /* Skip mirrors */
+ if (LocationIsMirror (L)) {
+ continue;
+ }
+
+ /* The chip must have an attribute "name" of type string */
+ Index = LocationGetAttr (L, "name");
+ D = CollAt (&L->Attributes, Index);
+ CfgDataCheckType (D, CfgDataString);
+
+ /* Remove the "name" attribute from the attribute list */
+ CollDelete (&L->Attributes, Index);
+
+ /* Create the chip instance for the address range */
+ Range = L->End - L->Start;
+ CI = NewChipInstance (D->V.SVal, L->Start, Range, &L->Attributes);
+
+ /* Delete the "name" attribute */
+ FreeCfgData (D);
+
+ /* Assign the chip instance to memory */
+ MemAssignChip (CI, L->Start, Range);
+ }
+
+ /* Create the mirrors */
+ for (I = 0; I < CollCount (&Locations); ++I) {
+
+ const CfgData* D;
+ unsigned MirrorAddr; /* Mirror address */
+ unsigned Range; /* Address range for this chip */
+ unsigned Offs; /* Offset of the mirror */
+ const ChipInstance* CI; /* Original chip instance */
+ ChipInstance* MCI; /* Mirrored chip instance */
+
+ /* Get this location */
+ const Location* L = CollAtUnchecked (&Locations, I);
+
+ /* Skip non mirrors */
+ if (!LocationIsMirror (L)) {
+ continue;
+ }
+
+ /* Calculate the address range */
+ Range = L->End - L->Start;
+
+ /* Get the mirror address */
+ D = CollConstAt (&L->Attributes, 0);
+ MirrorAddr = (unsigned) D->V.IVal;
+
+ /* For simplicity, get the chip instance we're mirroring from the
+ * memory, instead of searching for the range in the list.
+ */
+ CI = MemGetChip (MirrorAddr);
+ if (CI == 0) {
+ /* We are mirroring an unassigned address */
+ Error ("%s(%u): Mirroring an unassigned address",
+ CfgGetName (), L->Line);
+ }
+
+ /* Make sure we're mirroring the correct chip */
+ CHECK (MirrorAddr >= CI->Addr && MirrorAddr < CI->Addr + CI->Size);
+
+ /* Calculate the offset of the mirror */
+ Offs = MirrorAddr - CI->Addr;
+
+ /* Check if the mirror range is ok */
+ if (Offs + Range > CI->Size) {
+ Error ("%s(%u): Mirror range is too large", CfgGetName (), L->Line);
+ }
+
+ /* Clone the chip instance for the new location */
+ MCI = MirrorChipInstance (CI, L->Start - Offs);
+
+ /* Assign the chip instance to memory */
+ MemAssignChip (MCI, L->Start, Range);
+ }
}
Error ("Simulator configuration missing");
}
+ /* Initialize the simulated CPU memory */
+ MemInit ();
+
/* Read the config file */
CfgRead ();
- MemInit ();
+ /* Initialize the CPU */
CPUInit ();
#if 0
CPURun ();
/* common */
#include "coll.h"
+#include "xmalloc.h"
/* sim65 */
+#include "chip.h"
+#include "cputype.h"
#include "error.h"
#include "memory.h"
-/*****************************************************************************/
-/* Forwards */
-/*****************************************************************************/
-
-
-
-static void MemWrite (unsigned Addr, unsigned char Val);
-/* Write one byte to the memory cell */
-
-static unsigned char MemRead (unsigned Attr);
-/* Read one memory cell */
-
-
-
/*****************************************************************************/
/* Data */
/*****************************************************************************/
-/* RAM attributes */
-#define RA_READFUNC_MASK 0x000F /* Up to 16 read functions */
-#define RA_WRITEFUNC_MASK 0x00F0 /* Up to 16 write functions */
-#define RA_INITIALIZED 0x0100 /* Memory cell is initialized */
-#define RA_WPROT 0x0200 /* Memory cell is write protected */
-
-/* Defines reader and writer functions */
-#define RA_READFUNC_SHIFT 0
-#define RA_WRITEFUNC_SHIFT 4
-#define RA_READFUNC_MAX 16
-#define RA_WRITEFUNC_MAX 16
-
-/* Read/write function declarations */
-typedef unsigned char (*ReadFunc) (unsigned Addr);
-typedef void (*WriteFunc) (unsigned Addr, unsigned char Val);
-static Collection ReadFuncs = STATIC_COLLECTION_INITIALIZER;
-static Collection WriteFuncs = STATIC_COLLECTION_INITIALIZER;
-
-/* Memory attributes and the memory */
-static unsigned short MemAttr[0x10000];
-static unsigned char Mem[0x10000];
-
-
-
-/*****************************************************************************/
-/* Internal functions */
-/*****************************************************************************/
-
-
-
-static void MemWrite (unsigned Addr, unsigned char Val)
-/* Write one byte to the memory cell */
-{
- if (MemAttr[Addr] & RA_WPROT) {
- Warning ("Writing to write protected memory at $%04X", Addr);
- }
- Mem[Addr] = Val;
- MemAttr[Addr] |= RA_INITIALIZED;
-}
-
-
-
-static unsigned char MemRead (unsigned Addr)
-/* Read one memory cell */
-{
- if ((MemAttr[Addr] & RA_INITIALIZED) == 0) {
- /* We're reading a memory cell that was never written */
- Warning ("Reading from uninitialized memory at $%04X", Addr);
- }
- return Mem[Addr];
-}
+/* Pointer to our memory */
+static const ChipInstance** MemData = 0;
+unsigned MemSize = 0;
void MemWriteByte (unsigned Addr, unsigned char Val)
/* Write a byte to a memory location */
{
- /* Get the writer function */
- unsigned WI = (MemAttr[Addr] & RA_WRITEFUNC_MASK) >> RA_WRITEFUNC_SHIFT;
- WriteFunc WF = CollAt (&WriteFuncs, WI);
-
- /* Call the writer function */
- WF (Addr, Val);
+ /* Get the instance of the chip at this address */
+ const ChipInstance* CI = MemData[Addr];
+
+ /* Check if the memory is mapped */
+ if (CI == 0) {
+ Warning ("Writing to unassigned memory at $%06X", Addr);
+ } else {
+ CI->C->Data->Write (CI->Data, Addr - CI->Addr, Val);
+ }
}
unsigned char MemReadByte (unsigned Addr)
/* Read a byte from a memory location */
{
- /* Get the reader function */
- unsigned RI = (MemAttr[Addr] & RA_READFUNC_MASK) >> RA_READFUNC_SHIFT;
- ReadFunc RF = CollAt (&ReadFuncs, RI);
-
- /* Call the reader function */
- return RF (Addr);
+ /* Get the instance of the chip at this address */
+ const ChipInstance* CI = MemData[Addr];
+
+ /* Check if the memory is mapped */
+ if (CI == 0) {
+ Warning ("Reading from unassigned memory at $%06X", Addr);
+ return 0xFF;
+ } else {
+ return CI->C->Data->Read (CI->Data, Addr - CI->Addr);
+ }
}
unsigned MemReadZPWord (unsigned char Addr)
/* Read a word from the zero page. This function differs from ReadMemW in that
-* the read will always be in the zero page, even in case of an address
-* overflow.
-*/
+ * the read will always be in the zero page, even in case of an address
+ * overflow.
+ */
{
unsigned W = MemReadByte (Addr++);
return (W | (MemReadByte (Addr) << 8));
-void MemLoad (const char* Filename, unsigned Addr, unsigned Size)
-/* Load the contents of the given file into the RAM at the given address.
- * If Size is not zero, we will read exactly Size bytes from the file and
- * consider it an error if this is not possible. The memory attributes
- * for the range is set to initialized.
- */
+void MemAssignChip (const ChipInstance* CI, unsigned Addr, unsigned Range)
+/* Assign a chip instance to memory locations */
{
- unsigned BytesToRead;
- unsigned BytesRead;
- unsigned I;
+ /* Make sure, the addresses are in a valid range */
+ PRECONDITION (Addr + Range <= MemSize);
- /* Open the file */
- FILE* F = fopen (Filename, "rb");
- if (F == 0) {
- Error ("Cannot open `%s': %s", Filename, strerror (errno));
+ /* Assign the chip instance */
+ while (Range--) {
+ CHECK (MemData[Addr] == 0);
+ MemData[Addr++] = CI;
}
+}
- /* Set the number of bytes to read */
- BytesToRead = 0x10000 - Addr;
- if (Size > 0) {
- CHECK (Size <= BytesToRead); /* Must not exceed RAM */
- BytesToRead = Size;
- }
- /* Read data from the file */
- BytesRead = fread (Mem + Addr, 1, BytesToRead, F);
- if (ferror (F)) {
- Error ("Error reading from `%s': %s", Filename, strerror (errno));
- }
- if (Size > 0 && BytesRead != Size) {
- Error ("Cannot read %u bytes from `%s'", Size, Filename);
- }
- /* Close the file. Ignore errors, we were just reading. */
- fclose (F);
+const struct ChipInstance* MemGetChip (unsigned Addr)
+/* Get the chip that is located at the given address (may return NULL). */
+{
+ /* Make sure, the address is valid */
+ PRECONDITION (Addr < MemSize);
- /* Set the memory attribute for the range to initialized */
- for (I = 0; I < BytesRead; ++I) {
- MemAttr[Addr+I] |= RA_INITIALIZED;
- }
+ /* Return the chip instance */
+ return MemData[Addr];
}
{
unsigned I;
- /* Clear the memory and it's attributes. Writing zeroes to the
- * attribute array will cause any special flags to be reset and
- * the default read and write functions to be used.
- */
- for (I = 0; I < sizeof (Mem) / sizeof (Mem[0]); ++I) {
- Mem[I] = 0;
- }
- for (I = 0; I < sizeof (MemAttr) / sizeof (MemAttr[0]); ++I) {
- MemAttr[I] = 0;
+ /* Allocate memory depending on the CPU type */
+ switch (CPU) {
+ case CPU_6502:
+ case CPU_65C02:
+ MemSize = 0x10000;
+ break;
+ default:
+ Internal ("Unexpected CPU type: %d", CPU);
}
+ MemData = xmalloc (MemSize);
- /* Add the default reader and writer functions to the collection */
- CollAppend (&ReadFuncs, MemRead);
- CollAppend (&WriteFuncs, MemWrite);
-
- MemWriteByte (0xFFFC, 0x00);
- MemWriteByte (0xFFFD, 0x02);
+ /* Clear the memory */
+ for (I = 0; I < MemSize; ++I) {
+ MemData[I] = 0;
+ }
}
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
+/* Forwards */
+struct ChipInstance;
+
+/* Memory size of the CPU */
+extern unsigned MemSize;
+
+
+
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
* overflow.
*/
-void MemLoad (const char* Filename, unsigned Addr, unsigned Size);
-/* Load the contents of the given file into the RAM at the given address.
- * If Size is not zero, we will read exactly Size bytes from the file and
- * consider it an error if this is not possible. The memory attributes
- * for the range is set to initialized.
- */
+void MemAssignChip (const struct ChipInstance* CI, unsigned Addr, unsigned Range);
+/* Assign a chip instance to memory locations */
+
+const struct ChipInstance* MemGetChip (unsigned Addr);
+/* Get the chip that is located at the given address (may return NULL). */
void MemInit (void);
/* Initialize the memory subsystem */
+