git-svn-id: svn://svn.cc65.org/cc65/trunk@2092 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz
2003-04-27 15:31:00 +00:00
parent 251547f028
commit 8bff858b09
6 changed files with 293 additions and 239 deletions

View File

@@ -41,6 +41,7 @@
#include "xmalloc.h" #include "xmalloc.h"
/* sim65 */ /* sim65 */
#include "cfgdata.h"
#include "chipdata.h" #include "chipdata.h"
#include "chiplib.h" #include "chiplib.h"
#include "error.h" #include "error.h"
@@ -88,50 +89,6 @@ static int CmpChips (void* Data attribute ((unused)),
/*****************************************************************************/
/* Code */
/*****************************************************************************/
Chip* NewChip (ChipLibrary* Library, const ChipData* Data)
/* Allocate a new chip structure, initialize and return it */
{
/* Allocate memory */
Chip* C = xmalloc (sizeof (Chip));
/* Initialize the fields */
C->Library = Library;
C->Data = Data;
C->Instances = EmptyCollection;
/* Insert the new chip into the collection of all chips */
CollAppend (&Chips, C);
/* Return the structure */
return C;
}
ChipInstance* NewChipInstance (unsigned long Addr, unsigned Size)
/* Allocate a new chip instance for the chip. */
{
/* 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;
}
static Chip* FindChip (const char* Name) static Chip* FindChip (const char* Name)
/* Find a chip by name. Returns the Chip data structure or NULL if the chip /* Find a chip by name. Returns the Chip data structure or NULL if the chip
* could not be found. * could not be found.
@@ -158,24 +115,80 @@ static Chip* FindChip (const char* Name)
void InitChipInstance (ChipInstance* CI, const char* ChipName, /*****************************************************************************/
const struct CfgData** Data, unsigned Count) /* Code */
/* 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.
*/
Chip* NewChip (ChipLibrary* Library, const ChipData* Data)
/* Allocate a new chip structure, initialize and return it */
{ {
/* Allocate memory */
Chip* C = xmalloc (sizeof (Chip));
/* Initialize the fields */
C->Library = Library;
C->Data = Data;
C->Instances = EmptyCollection;
/* Insert the new chip into the collection of all chips */
CollAppend (&Chips, C);
/* Return the structure */
return C;
}
ChipInstance* NewChipInstance (const char* ChipName, unsigned Addr,
unsigned Size, const Collection* Attributes)
{
ChipInstance* CI;
/* Find the chip with the given name */ /* Find the chip with the given name */
Chip* C = FindChip (ChipName); Chip* C = FindChip (ChipName);
if (C == 0) { if (C == 0) {
Error ("No chip `%s' found for address $%6lX", ChipName, CI->Addr); Error ("No chip `%s' found for address $%06X", ChipName, Addr);
} }
/* Call the initialization function */ /* Allocate a new ChipInstance structure */
CI->InstanceData = C->Data->InitInstance (CI->Addr, CI->Size, Data, Count); CI = xmalloc (sizeof (*CI));
/* 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));
/* Assign the chip instance to the chip */ /* Assign the chip instance to the chip */
CI->C = C;
CollAppend (&C->Instances, CI); CollAppend (&C->Instances, CI);
/* Return the new instance struct */
return CI;
}
ChipInstance* MirrorChipInstance (const ChipInstance* Orig, unsigned Addr)
/* Generate a chip instance mirror and return it. */
{
/* Allocate a new ChipInstance structure */
ChipInstance* CI = xmalloc (sizeof (*CI));
/* 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 */
CollAppend (&CI->C->Instances, CI);
/* Return the new instance struct */
return CI;
} }

View File

@@ -62,9 +62,9 @@ typedef struct ChipInstance ChipInstance;
/* One instance of a chip */ /* One instance of a chip */
struct ChipInstance { struct ChipInstance {
Chip* C; /* Pointer to corresponding chip */ Chip* C; /* Pointer to corresponding chip */
unsigned long Addr; /* Start address of range */ unsigned Addr; /* Start address of range */
unsigned Size; /* Size of range */ unsigned Size; /* Size of range */
void* InstanceData; /* Chip instance data */ void* Data; /* Chip instance data */
}; };
/* Chip structure */ /* Chip structure */
@@ -85,14 +85,12 @@ struct Chip {
Chip* NewChip (struct ChipLibrary* Library, const ChipData* Data); Chip* NewChip (struct ChipLibrary* Library, const ChipData* Data);
/* Allocate a new chip structure, initialize and return it */ /* 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. */ /* Allocate a new chip instance for the chip. */
void InitChipInstance (ChipInstance* CI, const char* ChipName, ChipInstance* MirrorChipInstance (const ChipInstance* Orig, unsigned Addr);
const struct CfgData** Data, unsigned Count); /* Generate a chip instance mirror and return it. */
/* 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.
*/
void SortChips (void); void SortChips (void);
/* Sort all chips by name. Called after loading */ /* Sort all chips by name. Called after loading */

View File

@@ -50,6 +50,7 @@
#include "chip.h" #include "chip.h"
#include "error.h" #include "error.h"
#include "global.h" #include "global.h"
#include "memory.h"
#include "scanner.h" #include "scanner.h"
#include "config.h" #include "config.h"
@@ -67,8 +68,8 @@ static Collection Locations;
/* One memory location */ /* One memory location */
typedef struct Location Location; typedef struct Location Location;
struct Location { struct Location {
unsigned long Start; /* Start of memory location */ unsigned Start; /* Start of memory location */
unsigned long End; /* End memory location */ unsigned End; /* End memory location */
Collection Attributes; /* Attributes given */ Collection Attributes; /* Attributes given */
unsigned Line; /* Line in config file */ unsigned Line; /* Line in config file */
unsigned Col; /* Column in config file */ unsigned Col; /* Column in config file */
@@ -105,6 +106,30 @@ static CfgData* NewCfgData (void)
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 */ /* struct Location */
/*****************************************************************************/ /*****************************************************************************/
@@ -150,9 +175,9 @@ static int CmpLocations (void* Data attribute ((unused)),
static const CfgData* LocationFindAttr (const Location* L, const char* AttrName) static int LocationFindAttr (const Location* L, const char* AttrName)
/* Find the attribute with the given name and return it. Return NULL if the /* Find the attribute with the given name and return its index. Return -1 if
* attribute was not found. * the attribute was not found.
*/ */
{ {
unsigned I; unsigned I;
@@ -166,12 +191,26 @@ static const CfgData* LocationFindAttr (const Location* L, const char* AttrName)
/* Compare the name */ /* Compare the name */
if (StrCaseCmp (D->Attr, AttrName) == 0) { if (StrCaseCmp (D->Attr, AttrName) == 0) {
/* Found */ /* Found */
return D; return I;
} }
} }
/* Not found */ /* Not found */
return 0; return -1;
}
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.
*/
{
int I = LocationFindAttr (L, AttrName);
if (I < 0) {
Error ("%s(%u): Attribute `%s' missing", CfgGetName(), L->Line, AttrName);
}
return I;
} }
@@ -180,7 +219,7 @@ static int LocationIsMirror (const Location* L)
/* Return true if the given location is a mirror of another one. */ /* Return true if the given location is a mirror of another one. */
{ {
/* Find the "mirror" attribute */ /* Find the "mirror" attribute */
return (LocationFindAttr (L, "mirror") != 0); return (LocationFindAttr (L, "mirror") >= 0);
} }
@@ -191,29 +230,6 @@ static int LocationIsMirror (const Location* L)
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.
*/
{
if (*Flags & Mask) {
CfgError ("%s is already defined", Name);
}
*Flags |= Mask;
}
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);
}
}
static void ParseMemory (void) static void ParseMemory (void)
/* Parse a MEMORY section */ /* Parse a MEMORY section */
{ {
@@ -312,19 +328,106 @@ static void ParseMemory (void)
if (LocationIsMirror (L)) { if (LocationIsMirror (L)) {
const CfgData* D; const CfgData* D;
if (CollCount (&L->Attributes) > 1) { 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); "but has attributes", CfgGetName(), L->Line, L->Start);
} }
D = CollConstAt (&L->Attributes, 0); D = CollConstAt (&L->Attributes, 0);
if (D->Type != CfgDataNumber) { CfgDataCheckType (D, CfgDataNumber);
Error ("%s(%u): Mirror attribute is not an integer",
CfgGetName (), L->Line);
}
} }
/* Remember this entry */ /* Remember this entry */
Last = L; 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);
}
} }

View File

@@ -292,10 +292,13 @@ int main (int argc, char* argv[])
Error ("Simulator configuration missing"); Error ("Simulator configuration missing");
} }
/* Initialize the simulated CPU memory */
MemInit ();
/* Read the config file */ /* Read the config file */
CfgRead (); CfgRead ();
MemInit (); /* Initialize the CPU */
CPUInit (); CPUInit ();
#if 0 #if 0
CPURun (); CPURun ();

View File

@@ -39,84 +39,25 @@
/* common */ /* common */
#include "coll.h" #include "coll.h"
#include "xmalloc.h"
/* sim65 */ /* sim65 */
#include "chip.h"
#include "cputype.h"
#include "error.h" #include "error.h"
#include "memory.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 */ /* Data */
/*****************************************************************************/ /*****************************************************************************/
/* RAM attributes */ /* Pointer to our memory */
#define RA_READFUNC_MASK 0x000F /* Up to 16 read functions */ static const ChipInstance** MemData = 0;
#define RA_WRITEFUNC_MASK 0x00F0 /* Up to 16 write functions */ unsigned MemSize = 0;
#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];
}
@@ -129,12 +70,15 @@ static unsigned char MemRead (unsigned Addr)
void MemWriteByte (unsigned Addr, unsigned char Val) void MemWriteByte (unsigned Addr, unsigned char Val)
/* Write a byte to a memory location */ /* Write a byte to a memory location */
{ {
/* Get the writer function */ /* Get the instance of the chip at this address */
unsigned WI = (MemAttr[Addr] & RA_WRITEFUNC_MASK) >> RA_WRITEFUNC_SHIFT; const ChipInstance* CI = MemData[Addr];
WriteFunc WF = CollAt (&WriteFuncs, WI);
/* Call the writer function */ /* Check if the memory is mapped */
WF (Addr, Val); if (CI == 0) {
Warning ("Writing to unassigned memory at $%06X", Addr);
} else {
CI->C->Data->Write (CI->Data, Addr - CI->Addr, Val);
}
} }
@@ -142,12 +86,16 @@ void MemWriteByte (unsigned Addr, unsigned char Val)
unsigned char MemReadByte (unsigned Addr) unsigned char MemReadByte (unsigned Addr)
/* Read a byte from a memory location */ /* Read a byte from a memory location */
{ {
/* Get the reader function */ /* Get the instance of the chip at this address */
unsigned RI = (MemAttr[Addr] & RA_READFUNC_MASK) >> RA_READFUNC_SHIFT; const ChipInstance* CI = MemData[Addr];
ReadFunc RF = CollAt (&ReadFuncs, RI);
/* Call the reader function */ /* Check if the memory is mapped */
return RF (Addr); if (CI == 0) {
Warning ("Reading from unassigned memory at $%06X", Addr);
return 0xFF;
} else {
return CI->C->Data->Read (CI->Data, Addr - CI->Addr);
}
} }
@@ -163,9 +111,9 @@ unsigned MemReadWord (unsigned Addr)
unsigned MemReadZPWord (unsigned char Addr) unsigned MemReadZPWord (unsigned char Addr)
/* Read a word from the zero page. This function differs from ReadMemW in that /* 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 * the read will always be in the zero page, even in case of an address
* overflow. * overflow.
*/ */
{ {
unsigned W = MemReadByte (Addr++); unsigned W = MemReadByte (Addr++);
return (W | (MemReadByte (Addr) << 8)); return (W | (MemReadByte (Addr) << 8));
@@ -173,46 +121,29 @@ unsigned MemReadZPWord (unsigned char Addr)
void MemLoad (const char* Filename, unsigned Addr, unsigned Size) void MemAssignChip (const ChipInstance* CI, unsigned Addr, unsigned Range)
/* Load the contents of the given file into the RAM at the given address. /* Assign a chip instance to memory locations */
* 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.
*/
{ {
unsigned BytesToRead; /* Make sure, the addresses are in a valid range */
unsigned BytesRead; PRECONDITION (Addr + Range <= MemSize);
unsigned I;
/* Open the file */ /* Assign the chip instance */
FILE* F = fopen (Filename, "rb"); while (Range--) {
if (F == 0) { CHECK (MemData[Addr] == 0);
Error ("Cannot open `%s': %s", Filename, strerror (errno)); 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. */ const struct ChipInstance* MemGetChip (unsigned Addr)
fclose (F); /* 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 */ /* Return the chip instance */
for (I = 0; I < BytesRead; ++I) { return MemData[Addr];
MemAttr[Addr+I] |= RA_INITIALIZED;
}
} }
@@ -222,23 +153,21 @@ void MemInit (void)
{ {
unsigned I; unsigned I;
/* Clear the memory and it's attributes. Writing zeroes to the /* Allocate memory depending on the CPU type */
* attribute array will cause any special flags to be reset and switch (CPU) {
* the default read and write functions to be used. case CPU_6502:
*/ case CPU_65C02:
for (I = 0; I < sizeof (Mem) / sizeof (Mem[0]); ++I) { MemSize = 0x10000;
Mem[I] = 0; break;
default:
Internal ("Unexpected CPU type: %d", CPU);
} }
for (I = 0; I < sizeof (MemAttr) / sizeof (MemAttr[0]); ++I) { MemData = xmalloc (MemSize);
MemAttr[I] = 0;
/* Clear the memory */
for (I = 0; I < MemSize; ++I) {
MemData[I] = 0;
} }
/* Add the default reader and writer functions to the collection */
CollAppend (&ReadFuncs, MemRead);
CollAppend (&WriteFuncs, MemWrite);
MemWriteByte (0xFFFC, 0x00);
MemWriteByte (0xFFFD, 0x02);
} }

View File

@@ -44,6 +44,14 @@
/* Forwards */
struct ChipInstance;
/* Memory size of the CPU */
extern unsigned MemSize;
/*****************************************************************************/ /*****************************************************************************/
/* Code */ /* Code */
/*****************************************************************************/ /*****************************************************************************/
@@ -65,12 +73,11 @@ unsigned MemReadZPWord (unsigned char Addr);
* overflow. * overflow.
*/ */
void MemLoad (const char* Filename, unsigned Addr, unsigned Size); void MemAssignChip (const struct ChipInstance* CI, unsigned Addr, unsigned Range);
/* Load the contents of the given file into the RAM at the given address. /* Assign a chip instance to memory locations */
* 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 const struct ChipInstance* MemGetChip (unsigned Addr);
* for the range is set to initialized. /* Get the chip that is located at the given address (may return NULL). */
*/
void MemInit (void); void MemInit (void);
/* Initialize the memory subsystem */ /* Initialize the memory subsystem */
@@ -83,3 +90,4 @@ void MemInit (void);