moved all globals into a single global struct -> 3% speedup with clang :)
This commit is contained in:
parent
b3f4c56541
commit
b8af4edbbe
252
perfect6502.c
252
perfect6502.c
|
@ -117,18 +117,57 @@ get_bitmap(bitmap_t *bitmap, int index)
|
|||
*
|
||||
************************************************************/
|
||||
|
||||
/* everything that describes a node */
|
||||
DECLARE_BITMAP(nodes_pullup, NODES);
|
||||
DECLARE_BITMAP(nodes_pulldown, NODES);
|
||||
DECLARE_BITMAP(nodes_value, NODES);
|
||||
nodenum_t nodes_gates[NODES][NODES];
|
||||
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];
|
||||
/* list of nodes that need to be recalculated */
|
||||
typedef struct {
|
||||
nodenum_t *list;
|
||||
count_t count;
|
||||
} list_t;
|
||||
|
||||
typedef struct {
|
||||
/* everything that describes a node */
|
||||
DECLARE_BITMAP(nodes_pullup, NODES);
|
||||
DECLARE_BITMAP(nodes_pulldown, NODES);
|
||||
DECLARE_BITMAP(nodes_value, NODES);
|
||||
nodenum_t nodes_gates[NODES][NODES];
|
||||
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];
|
||||
|
||||
/* everything that describes a transistor */
|
||||
nodenum_t transistors_gate[TRANSISTORS];
|
||||
nodenum_t transistors_c1[TRANSISTORS];
|
||||
nodenum_t transistors_c2[TRANSISTORS];
|
||||
DECLARE_BITMAP(transistors_on, TRANSISTORS);
|
||||
|
||||
/* the nodes we are working with */
|
||||
nodenum_t list1[NODES];
|
||||
list_t listin;
|
||||
|
||||
/* the indirect nodes we are collecting for the next run */
|
||||
nodenum_t list2[NODES];
|
||||
list_t listout;
|
||||
|
||||
DECLARE_BITMAP(listout_bitmap, NODES);
|
||||
|
||||
nodenum_t group[NODES];
|
||||
count_t groupcount;
|
||||
DECLARE_BITMAP(groupbitmap, NODES);
|
||||
|
||||
enum {
|
||||
contains_nothing,
|
||||
contains_hi,
|
||||
contains_pullup,
|
||||
contains_pulldown,
|
||||
contains_vcc,
|
||||
contains_vss
|
||||
} group_contains_value;
|
||||
} state_t;
|
||||
|
||||
state_t state;
|
||||
|
||||
/*
|
||||
* The "value" propertiy of VCC and GND is never evaluated in the code,
|
||||
|
@ -136,39 +175,39 @@ nodenum_t nodes_left_dependant[NODES][NODES];
|
|||
*/
|
||||
|
||||
static inline void
|
||||
set_nodes_pullup(transnum_t t, BOOL state)
|
||||
set_nodes_pullup(transnum_t t, BOOL s)
|
||||
{
|
||||
set_bitmap(nodes_pullup, t, state);
|
||||
set_bitmap(state.nodes_pullup, t, s);
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
get_nodes_pullup(transnum_t t)
|
||||
{
|
||||
return get_bitmap(nodes_pullup, t);
|
||||
return get_bitmap(state.nodes_pullup, t);
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_nodes_pulldown(transnum_t t, BOOL state)
|
||||
set_nodes_pulldown(transnum_t t, BOOL s)
|
||||
{
|
||||
set_bitmap(nodes_pulldown, t, state);
|
||||
set_bitmap(state.nodes_pulldown, t, s);
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
get_nodes_pulldown(transnum_t t)
|
||||
{
|
||||
return get_bitmap(nodes_pulldown, t);
|
||||
return get_bitmap(state.nodes_pulldown, t);
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_nodes_value(transnum_t t, BOOL state)
|
||||
set_nodes_value(transnum_t t, BOOL s)
|
||||
{
|
||||
set_bitmap(nodes_value, t, state);
|
||||
set_bitmap(state.nodes_value, t, s);
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
get_nodes_value(transnum_t t)
|
||||
{
|
||||
return get_bitmap(nodes_value, t);
|
||||
return get_bitmap(state.nodes_value, t);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
|
@ -177,30 +216,24 @@ get_nodes_value(transnum_t t)
|
|||
*
|
||||
************************************************************/
|
||||
|
||||
/* everything that describes a transistor */
|
||||
nodenum_t transistors_gate[TRANSISTORS];
|
||||
nodenum_t transistors_c1[TRANSISTORS];
|
||||
nodenum_t transistors_c2[TRANSISTORS];
|
||||
DECLARE_BITMAP(transistors_on, TRANSISTORS);
|
||||
|
||||
#ifdef BROKEN_TRANSISTORS
|
||||
unsigned int broken_transistor = (unsigned int)-1;
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
set_transistors_on(transnum_t t, BOOL state)
|
||||
set_transistors_on(transnum_t t, BOOL s)
|
||||
{
|
||||
#ifdef BROKEN_TRANSISTORS
|
||||
if (t == broken_transistor)
|
||||
return;
|
||||
#endif
|
||||
set_bitmap(transistors_on, t, state);
|
||||
set_bitmap(state.transistors_on, t, s);
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
get_transistors_on(transnum_t t)
|
||||
{
|
||||
return get_bitmap(transistors_on, t);
|
||||
return get_bitmap(state.transistors_on, t);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
|
@ -209,59 +242,39 @@ get_transistors_on(transnum_t t)
|
|||
*
|
||||
************************************************************/
|
||||
|
||||
/* list of nodes that need to be recalculated */
|
||||
typedef struct {
|
||||
nodenum_t *list;
|
||||
count_t count;
|
||||
} list_t;
|
||||
|
||||
/* the nodes we are working with */
|
||||
nodenum_t list1[NODES];
|
||||
list_t listin = {
|
||||
.list = list1,
|
||||
};
|
||||
|
||||
/* the indirect nodes we are collecting for the next run */
|
||||
nodenum_t list2[NODES];
|
||||
list_t listout = {
|
||||
.list = list2,
|
||||
};
|
||||
|
||||
DECLARE_BITMAP(listout_bitmap, NODES);
|
||||
|
||||
static inline nodenum_t
|
||||
listin_get(count_t i)
|
||||
{
|
||||
return listin.list[i];
|
||||
return state.listin.list[i];
|
||||
}
|
||||
|
||||
static inline count_t
|
||||
listin_count()
|
||||
{
|
||||
return listin.count;
|
||||
return state.listin.count;
|
||||
}
|
||||
|
||||
static inline void
|
||||
lists_switch()
|
||||
{
|
||||
list_t tmp = listin;
|
||||
listin = listout;
|
||||
listout = tmp;
|
||||
list_t tmp = state.listin;
|
||||
state.listin = state.listout;
|
||||
state.listout = tmp;
|
||||
}
|
||||
|
||||
static inline void
|
||||
listout_clear()
|
||||
{
|
||||
listout.count = 0;
|
||||
bitmap_clear(listout_bitmap, NODES);
|
||||
state.listout.count = 0;
|
||||
bitmap_clear(state.listout_bitmap, NODES);
|
||||
}
|
||||
|
||||
static inline void
|
||||
listout_add(nodenum_t i)
|
||||
{
|
||||
if (!get_bitmap(listout_bitmap, i)) {
|
||||
listout.list[listout.count++] = i;
|
||||
set_bitmap(listout_bitmap, i, 1);
|
||||
if (!get_bitmap(state.listout_bitmap, i)) {
|
||||
state.listout.list[state.listout.count++] = i;
|
||||
set_bitmap(state.listout_bitmap, i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,40 +291,37 @@ listout_add(nodenum_t i)
|
|||
* we use an array and a count for O(1) insert and
|
||||
* iteration, and a redundant bitmap for O(1) lookup
|
||||
*/
|
||||
static nodenum_t group[NODES];
|
||||
static count_t groupcount;
|
||||
DECLARE_BITMAP(groupbitmap, NODES);
|
||||
|
||||
static inline void
|
||||
group_clear()
|
||||
{
|
||||
groupcount = 0;
|
||||
bitmap_clear(groupbitmap, NODES);
|
||||
state.groupcount = 0;
|
||||
bitmap_clear(state.groupbitmap, NODES);
|
||||
}
|
||||
|
||||
static inline void
|
||||
group_add(nodenum_t i)
|
||||
{
|
||||
group[groupcount++] = i;
|
||||
set_bitmap(groupbitmap, i, 1);
|
||||
state.group[state.groupcount++] = i;
|
||||
set_bitmap(state.groupbitmap, i, 1);
|
||||
}
|
||||
|
||||
static inline nodenum_t
|
||||
group_get(count_t n)
|
||||
{
|
||||
return group[n];
|
||||
return state.group[n];
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
group_contains(nodenum_t el)
|
||||
{
|
||||
return get_bitmap(groupbitmap, el);
|
||||
return get_bitmap(state.groupbitmap, el);
|
||||
}
|
||||
|
||||
static inline count_t
|
||||
group_count()
|
||||
{
|
||||
return groupcount;
|
||||
return state.groupcount;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
|
@ -320,15 +330,6 @@ group_count()
|
|||
*
|
||||
************************************************************/
|
||||
|
||||
enum {
|
||||
contains_nothing,
|
||||
contains_hi,
|
||||
contains_pullup,
|
||||
contains_pulldown,
|
||||
contains_vcc,
|
||||
contains_vss
|
||||
} group_contains_value;
|
||||
|
||||
static void
|
||||
addNodeToGroup(nodenum_t n)
|
||||
{
|
||||
|
@ -338,12 +339,12 @@ addNodeToGroup(nodenum_t n)
|
|||
* the fact that they are connected to vcc or vss.
|
||||
*/
|
||||
if (n == vss) {
|
||||
group_contains_value = contains_vss;
|
||||
state.group_contains_value = contains_vss;
|
||||
return;
|
||||
}
|
||||
if (n == vcc) {
|
||||
if (group_contains_value != contains_vss)
|
||||
group_contains_value = contains_vcc;
|
||||
if (state.group_contains_value != contains_vss)
|
||||
state.group_contains_value = contains_vcc;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -352,26 +353,26 @@ addNodeToGroup(nodenum_t n)
|
|||
|
||||
group_add(n);
|
||||
|
||||
if (group_contains_value < contains_pulldown && get_nodes_pulldown(n)) {
|
||||
group_contains_value = contains_pulldown;
|
||||
if (state.group_contains_value < contains_pulldown && get_nodes_pulldown(n)) {
|
||||
state.group_contains_value = contains_pulldown;
|
||||
}
|
||||
if (group_contains_value < contains_pullup && get_nodes_pullup(n)) {
|
||||
group_contains_value = contains_pullup;
|
||||
if (state.group_contains_value < contains_pullup && get_nodes_pullup(n)) {
|
||||
state.group_contains_value = contains_pullup;
|
||||
}
|
||||
if (group_contains_value < contains_hi && get_nodes_value(n)) {
|
||||
group_contains_value = contains_hi;
|
||||
if (state.group_contains_value < contains_hi && get_nodes_value(n)) {
|
||||
state.group_contains_value = contains_hi;
|
||||
}
|
||||
|
||||
/* revisit all transistors that control this node */
|
||||
for (count_t t = 0; t < nodes_c1c2count[n]; t++) {
|
||||
transnum_t tn = nodes_c1c2s[n][t];
|
||||
for (count_t t = 0; t < state.nodes_c1c2count[n]; t++) {
|
||||
transnum_t tn = state.nodes_c1c2s[n][t];
|
||||
/* if the transistor connects c1 and c2... */
|
||||
if (get_transistors_on(tn)) {
|
||||
/* if original node was connected to c1, continue with c2 */
|
||||
if (transistors_c1[tn] == n)
|
||||
addNodeToGroup(transistors_c2[tn]);
|
||||
if (state.transistors_c1[tn] == n)
|
||||
addNodeToGroup(state.transistors_c2[tn]);
|
||||
else
|
||||
addNodeToGroup(transistors_c1[tn]);
|
||||
addNodeToGroup(state.transistors_c1[tn]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -381,7 +382,7 @@ addAllNodesToGroup(node)
|
|||
{
|
||||
group_clear();
|
||||
|
||||
group_contains_value = contains_nothing;
|
||||
state.group_contains_value = contains_nothing;
|
||||
|
||||
addNodeToGroup(node);
|
||||
}
|
||||
|
@ -389,7 +390,7 @@ addAllNodesToGroup(node)
|
|||
static inline BOOL
|
||||
getGroupValue()
|
||||
{
|
||||
switch (group_contains_value) {
|
||||
switch (state.group_contains_value) {
|
||||
case contains_vcc:
|
||||
case contains_pullup:
|
||||
case contains_hi:
|
||||
|
@ -423,18 +424,18 @@ recalcNode(nodenum_t node)
|
|||
nodenum_t nn = group_get(i);
|
||||
if (get_nodes_value(nn) != newv) {
|
||||
set_nodes_value(nn, newv);
|
||||
for (count_t t = 0; t < nodes_gatecount[nn]; t++) {
|
||||
transnum_t tn = nodes_gates[nn][t];
|
||||
for (count_t t = 0; t < state.nodes_gatecount[nn]; t++) {
|
||||
transnum_t tn = state.nodes_gates[nn][t];
|
||||
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]);
|
||||
for (count_t g = 0; g < state.nodes_left_dependants[nn]; g++) {
|
||||
listout_add(state.nodes_left_dependant[nn][g]);
|
||||
}
|
||||
} else {
|
||||
for (count_t g = 0; g < nodes_dependants[nn]; g++) {
|
||||
listout_add(nodes_dependant[nn][g]);
|
||||
for (count_t g = 0; g < state.nodes_dependants[nn]; g++) {
|
||||
listout_add(state.nodes_dependant[nn][g]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -683,21 +684,21 @@ unsigned int transistors;
|
|||
static inline void
|
||||
add_nodes_dependant(nodenum_t a, nodenum_t b)
|
||||
{
|
||||
for (count_t g = 0; g < nodes_dependants[a]; g++)
|
||||
if (nodes_dependant[a][g] == b)
|
||||
for (count_t g = 0; g < state.nodes_dependants[a]; g++)
|
||||
if (state.nodes_dependant[a][g] == b)
|
||||
return;
|
||||
|
||||
nodes_dependant[a][nodes_dependants[a]++] = b;
|
||||
state.nodes_dependant[a][state.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)
|
||||
for (count_t g = 0; g < state.nodes_left_dependants[a]; g++)
|
||||
if (state.nodes_left_dependant[a][g] == b)
|
||||
return;
|
||||
|
||||
nodes_left_dependant[a][nodes_left_dependants[a]++] = b;
|
||||
state.nodes_left_dependant[a][state.nodes_left_dependants[a]++] = b;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -707,8 +708,8 @@ setupNodesAndTransistors()
|
|||
/* copy nodes into r/w data structure */
|
||||
for (i = 0; i < NODES; i++) {
|
||||
set_nodes_pullup(i, segdefs[i] == 1);
|
||||
nodes_gatecount[i] = 0;
|
||||
nodes_c1c2count[i] = 0;
|
||||
state.nodes_gatecount[i] = 0;
|
||||
state.nodes_c1c2count[i] = 0;
|
||||
}
|
||||
/* copy transistors into r/w data structure */
|
||||
count_t j = 0;
|
||||
|
@ -731,9 +732,9 @@ setupNodesAndTransistors()
|
|||
}
|
||||
#endif
|
||||
if (!found) {
|
||||
transistors_gate[j] = gate;
|
||||
transistors_c1[j] = c1;
|
||||
transistors_c2[j] = c2;
|
||||
state.transistors_gate[j] = gate;
|
||||
state.transistors_c1[j] = c1;
|
||||
state.transistors_c2[j] = c2;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
@ -744,24 +745,24 @@ setupNodesAndTransistors()
|
|||
|
||||
/* cross reference transistors in nodes data structures */
|
||||
for (i = 0; i < transistors; i++) {
|
||||
nodenum_t gate = transistors_gate[i];
|
||||
nodenum_t c1 = transistors_c1[i];
|
||||
nodenum_t c2 = transistors_c2[i];
|
||||
nodes_gates[gate][nodes_gatecount[gate]++] = i;
|
||||
nodes_c1c2s[c1][nodes_c1c2count[c1]++] = i;
|
||||
nodes_c1c2s[c2][nodes_c1c2count[c2]++] = i;
|
||||
nodenum_t gate = state.transistors_gate[i];
|
||||
nodenum_t c1 = state.transistors_c1[i];
|
||||
nodenum_t c2 = state.transistors_c2[i];
|
||||
state.nodes_gates[gate][state.nodes_gatecount[gate]++] = i;
|
||||
state.nodes_c1c2s[c1][state.nodes_c1c2count[c1]++] = i;
|
||||
state.nodes_c1c2s[c2][state.nodes_c1c2count[c2]++] = i;
|
||||
}
|
||||
|
||||
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];
|
||||
nodenum_t c1 = transistors_c1[t];
|
||||
state.nodes_dependants[i] = 0;
|
||||
state.nodes_left_dependants[i] = 0;
|
||||
for (count_t g = 0; g < state.nodes_gatecount[i]; g++) {
|
||||
transnum_t t = state.nodes_gates[i][g];
|
||||
nodenum_t c1 = state.transistors_c1[t];
|
||||
if (c1 != vss && c1 != vcc) {
|
||||
add_nodes_dependant(i, c1);
|
||||
}
|
||||
nodenum_t c2 = transistors_c2[t];
|
||||
nodenum_t c2 = state.transistors_c2[t];
|
||||
if (c2 != vss && c2 != vcc) {
|
||||
add_nodes_dependant(i, c2);
|
||||
}
|
||||
|
@ -811,6 +812,9 @@ resetChip()
|
|||
void
|
||||
initAndResetChip()
|
||||
{
|
||||
state.listin.list = state.list1;
|
||||
state.listout.list = state.list2;
|
||||
|
||||
/* set up data structures for efficient emulation */
|
||||
setupNodesAndTransistors();
|
||||
|
||||
|
|
Loading…
Reference in New Issue