mirror of
https://github.com/mist64/perfect6502.git
synced 2024-12-27 20:29:43 +00:00
optimizations (~25%) and cleanup
Optimizations: 1. When a transistor is turned on, only add one of the nodes it controls to listout, otherwise group calculation would be done twice for this group. This simplifies recalcNodeList(). (This required the following change: Instead of adding the nodes that control transistors that have changed to listout, put the nodes that are switched by transistors on listout.) 2. The group value is calculated while collecting nodes, and the enum group_contains_value makes sure we don't check for weaker value indicators than have already been established. 3. listout is now a set, no node will be visited twice for group calculation, within one interation. 4. When setting input pins of the package to a value, only recalc the node if it actually changes. 5. Toggling a transistor is done by assigning it the group value instead of the inverse of its value. Cleanup: * Merge the concept of listin with the concept of nodes that change from the outside and trigger a recalc.
This commit is contained in:
parent
bdbe8eff59
commit
b2cce88620
1
emu.c
1
emu.c
@ -12,7 +12,6 @@ typedef uint8_t step_t;
|
||||
|
||||
static step_t t; /* step inside the instruction */
|
||||
static uint8_t ir; /* instruction register */
|
||||
static uint8_t operand;
|
||||
static uint16_t PC;
|
||||
static uint8_t A, X, Y, S, P;
|
||||
static uint8_t temp_lo, temp_hi;
|
||||
|
178
perfect6502.c
178
perfect6502.c
@ -126,7 +126,9 @@ nodenum_t nodes_c1c2s[NODES][2*NODES];
|
||||
count_t nodes_gatecount[NODES];
|
||||
count_t nodes_c1c2count[NODES];
|
||||
nodenum_t nodes_dependants[NODES];
|
||||
nodenum_t nodes_left_dependants[NODES];
|
||||
nodenum_t nodes_dependant[NODES][NODES];
|
||||
nodenum_t nodes_left_dependant[NODES][NODES];
|
||||
|
||||
/*
|
||||
* The "value" propertiy of VCC and GND is never evaluated in the code,
|
||||
@ -225,6 +227,8 @@ list_t listout = {
|
||||
.list = list2,
|
||||
};
|
||||
|
||||
DECLARE_BITMAP(listout_bitmap, NODES);
|
||||
|
||||
static inline nodenum_t
|
||||
listin_get(count_t i)
|
||||
{
|
||||
@ -249,12 +253,16 @@ static inline void
|
||||
listout_clear()
|
||||
{
|
||||
listout.count = 0;
|
||||
bitmap_clear(listout_bitmap, NODES);
|
||||
}
|
||||
|
||||
static inline void
|
||||
listout_add(nodenum_t i)
|
||||
{
|
||||
listout.list[listout.count++] = i;
|
||||
if (!get_bitmap(listout_bitmap, i)) {
|
||||
listout.list[listout.count++] = i;
|
||||
set_bitmap(listout_bitmap, i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
@ -265,7 +273,7 @@ listout_add(nodenum_t i)
|
||||
|
||||
/*
|
||||
* a group is a set of connected nodes, which consequently
|
||||
* share the same potential
|
||||
* share the same value
|
||||
*
|
||||
* we use an array and a count for O(1) insert and
|
||||
* iteration, and a redundant bitmap for O(1) lookup
|
||||
@ -312,29 +320,49 @@ group_count()
|
||||
*
|
||||
************************************************************/
|
||||
|
||||
BOOL group_contains_pullup;
|
||||
BOOL group_contains_pulldown;
|
||||
BOOL group_contains_hi;
|
||||
enum {
|
||||
contains_nothing,
|
||||
contains_hi,
|
||||
contains_pullup,
|
||||
contains_pulldown,
|
||||
contains_vcc,
|
||||
contains_vss
|
||||
} group_contains_value;
|
||||
|
||||
static void
|
||||
addNodeToGroup(nodenum_t n)
|
||||
{
|
||||
/*
|
||||
* We need to stop at vss and vcc, otherwise we'll revisit other groups
|
||||
* with the same value - just because they all derive their value from
|
||||
* the fact that they are connected to vcc or vss.
|
||||
*/
|
||||
if (n == vss) {
|
||||
group_contains_value = contains_vss;
|
||||
return;
|
||||
}
|
||||
if (n == vcc) {
|
||||
if (group_contains_value != contains_vss)
|
||||
group_contains_value = contains_vcc;
|
||||
return;
|
||||
}
|
||||
|
||||
if (group_contains(n))
|
||||
return;
|
||||
|
||||
group_add(n);
|
||||
|
||||
if (get_nodes_pullup(n))
|
||||
group_contains_pullup = YES;
|
||||
if (get_nodes_pulldown(n))
|
||||
group_contains_pulldown = YES;
|
||||
if (get_nodes_value(n))
|
||||
group_contains_hi = YES;
|
||||
if (group_contains_value < contains_pulldown && get_nodes_pulldown(n)) {
|
||||
group_contains_value = contains_pulldown;
|
||||
}
|
||||
if (group_contains_value < contains_pullup && get_nodes_pullup(n)) {
|
||||
group_contains_value = contains_pullup;
|
||||
}
|
||||
if (group_contains_value < contains_hi && get_nodes_value(n)) {
|
||||
group_contains_value = contains_hi;
|
||||
}
|
||||
|
||||
if (n == vss || n == vcc)
|
||||
return;
|
||||
|
||||
/* revisit all transistors that are controlled by this node */
|
||||
/* revisit all transistors that control this node */
|
||||
for (count_t t = 0; t < nodes_c1c2count[n]; t++) {
|
||||
transnum_t tn = nodes_c1c2s[n][t];
|
||||
/* if the transistor connects c1 and c2... */
|
||||
@ -353,9 +381,7 @@ addAllNodesToGroup(node)
|
||||
{
|
||||
group_clear();
|
||||
|
||||
group_contains_pullup = NO;
|
||||
group_contains_pulldown = NO;
|
||||
group_contains_hi = NO;
|
||||
group_contains_value = contains_nothing;
|
||||
|
||||
addNodeToGroup(node);
|
||||
}
|
||||
@ -363,19 +389,16 @@ addAllNodesToGroup(node)
|
||||
static inline BOOL
|
||||
getGroupValue()
|
||||
{
|
||||
if (group_contains(vss))
|
||||
return NO;
|
||||
|
||||
if (group_contains(vcc))
|
||||
return YES;
|
||||
|
||||
if (group_contains_pulldown)
|
||||
return NO;
|
||||
|
||||
if (group_contains_pullup)
|
||||
return YES;
|
||||
|
||||
return group_contains_hi;
|
||||
switch (group_contains_value) {
|
||||
case contains_vcc:
|
||||
case contains_pullup:
|
||||
case contains_hi:
|
||||
return YES;
|
||||
case contains_vss:
|
||||
case contains_pulldown:
|
||||
case contains_nothing:
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -402,24 +425,33 @@ recalcNode(nodenum_t node)
|
||||
set_nodes_value(nn, newv);
|
||||
for (count_t t = 0; t < nodes_gatecount[nn]; t++) {
|
||||
transnum_t tn = nodes_gates[nn][t];
|
||||
set_transistors_on(tn, !get_transistors_on(tn));
|
||||
set_transistors_on(tn, newv);
|
||||
}
|
||||
|
||||
if (newv) {
|
||||
for (count_t g = 0; g < nodes_left_dependants[nn]; g++) {
|
||||
listout_add(nodes_left_dependant[nn][g]);
|
||||
}
|
||||
} else {
|
||||
for (count_t g = 0; g < nodes_dependants[nn]; g++) {
|
||||
listout_add(nodes_dependant[nn][g]);
|
||||
}
|
||||
}
|
||||
listout_add(nn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
recalcNodeList(const nodenum_t *source, count_t count)
|
||||
recalcNodeList()
|
||||
{
|
||||
listout_clear();
|
||||
|
||||
for (count_t i = 0; i < count; i++)
|
||||
recalcNode(source[i]);
|
||||
|
||||
lists_switch();
|
||||
|
||||
for (int j = 0; j < 100; j++) { /* loop limiter */
|
||||
/*
|
||||
* make the secondary list our primary list, use
|
||||
* the data storage of the primary list as the
|
||||
* secondary list
|
||||
*/
|
||||
lists_switch();
|
||||
|
||||
if (!listin_count())
|
||||
break;
|
||||
|
||||
@ -434,25 +466,10 @@ recalcNodeList(const nodenum_t *source, count_t count)
|
||||
*/
|
||||
for (count_t i = 0; i < listin_count(); i++) {
|
||||
nodenum_t n = listin_get(i);
|
||||
for (count_t g = 0; g < nodes_dependants[n]; g++)
|
||||
recalcNode(nodes_dependant[n][g]);
|
||||
recalcNode(n);
|
||||
}
|
||||
/*
|
||||
* make the secondary list our primary list, use
|
||||
* the data storage of the primary list as the
|
||||
* secondary list
|
||||
*/
|
||||
lists_switch();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
recalcAllNodes()
|
||||
{
|
||||
nodenum_t temp[NODES];
|
||||
for (count_t i = 0; i < NODES; i++)
|
||||
temp[i] = i;
|
||||
recalcNodeList(temp, NODES);
|
||||
listout_clear();
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
@ -464,9 +481,12 @@ recalcAllNodes()
|
||||
static inline void
|
||||
setNode(nodenum_t nn, BOOL state)
|
||||
{
|
||||
set_nodes_pullup(nn, state);
|
||||
set_nodes_pulldown(nn, !state);
|
||||
recalcNodeList(&nn, 1);
|
||||
BOOL oldstate = get_nodes_pullup(nn);
|
||||
if (state != oldstate) {
|
||||
set_nodes_pullup(nn, state);
|
||||
set_nodes_pulldown(nn, !state);
|
||||
listout_add(nn);
|
||||
}
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
@ -593,11 +613,12 @@ chipStatus()
|
||||
readP(),
|
||||
readIR());
|
||||
|
||||
if (clk)
|
||||
if (clk) {
|
||||
if (r_w)
|
||||
printf(" R$%04X=$%02X", a, memory[a]);
|
||||
else
|
||||
printf(" W$%04X=$%02X", a, d);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@ -642,6 +663,7 @@ step()
|
||||
|
||||
/* invert clock */
|
||||
setNode(clk0, !clk);
|
||||
recalcNodeList();
|
||||
|
||||
/* handle memory reads and writes */
|
||||
if (!clk)
|
||||
@ -668,6 +690,16 @@ add_nodes_dependant(nodenum_t a, nodenum_t b)
|
||||
nodes_dependant[a][nodes_dependants[a]++] = b;
|
||||
}
|
||||
|
||||
static inline void
|
||||
add_nodes_left_dependant(nodenum_t a, nodenum_t b)
|
||||
{
|
||||
for (count_t g = 0; g < nodes_left_dependants[a]; g++)
|
||||
if (nodes_left_dependant[a][g] == b)
|
||||
return;
|
||||
|
||||
nodes_left_dependant[a][nodes_left_dependants[a]++] = b;
|
||||
}
|
||||
|
||||
void
|
||||
setupNodesAndTransistors()
|
||||
{
|
||||
@ -722,10 +754,22 @@ setupNodesAndTransistors()
|
||||
|
||||
for (i = 0; i < NODES; i++) {
|
||||
nodes_dependants[i] = 0;
|
||||
nodes_left_dependants[i] = 0;
|
||||
for (count_t g = 0; g < nodes_gatecount[i]; g++) {
|
||||
transnum_t t = nodes_gates[i][g];
|
||||
add_nodes_dependant(i, transistors_c1[t]);
|
||||
add_nodes_dependant(i, transistors_c2[t]);
|
||||
nodenum_t c1 = transistors_c1[t];
|
||||
if (c1 != vss && c1 != vcc) {
|
||||
add_nodes_dependant(i, c1);
|
||||
}
|
||||
nodenum_t c2 = transistors_c2[t];
|
||||
if (c2 != vss && c2 != vcc) {
|
||||
add_nodes_dependant(i, c2);
|
||||
}
|
||||
if (c1 != vss && c1 != vcc) {
|
||||
add_nodes_left_dependant(i, c1);
|
||||
} else {
|
||||
add_nodes_left_dependant(i, c2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -748,7 +792,10 @@ resetChip()
|
||||
setNode(irq, 1);
|
||||
setNode(nmi, 1);
|
||||
|
||||
recalcAllNodes();
|
||||
for (count_t i = 0; i < NODES; i++)
|
||||
listout_add(i);
|
||||
|
||||
recalcNodeList();
|
||||
|
||||
/* hold RESET for 8 cycles */
|
||||
for (int i = 0; i < 16; i++)
|
||||
@ -756,6 +803,7 @@ resetChip()
|
||||
|
||||
/* release RESET */
|
||||
setNode(res, 1);
|
||||
recalcNodeList();
|
||||
|
||||
cycle = 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user