185 lines
5.4 KiB
C
185 lines
5.4 KiB
C
|
|
//#include <assert.h>
|
|
|
|
struct Net;
|
|
struct Gate;
|
|
|
|
struct Gate {
|
|
int* in_queue;
|
|
int* port_states;
|
|
int** port_net_state;
|
|
int** port_net_state_num;
|
|
int** port_net_in_queue;
|
|
struct Net** port_nets_c;
|
|
int objref;
|
|
int logic_function;
|
|
int data_size;
|
|
int* data;
|
|
};
|
|
|
|
struct Net {
|
|
int* state;
|
|
int* state_num;
|
|
int* in_queue;
|
|
int* update_tick;
|
|
int* num_gates_update;
|
|
struct Gate** gates_update_c;
|
|
int id;
|
|
};
|
|
|
|
#define FAST static inline
|
|
#define DLL __attribute__((visibility("default")))
|
|
#define GATEFUNCTYPE
|
|
|
|
typedef void(*GateFunc)(const struct Gate* const gate);
|
|
|
|
struct Net** net_queue;
|
|
int* num_net_queue;
|
|
struct Gate** gate_queue;
|
|
int* num_gate_queue;
|
|
int* current_tick;
|
|
//static const int queue_max = 65536;
|
|
extern GateFunc sim_logic_functions[];
|
|
|
|
DLL void sim_set_data(struct Net** net_queue_in, int* num_net_queue_in, struct Gate** gate_queue_in, int* num_gate_queue_in, int* current_tick_in, int queue_max_in);
|
|
DLL void sim_update_nets();
|
|
DLL void sim_update_gates();
|
|
|
|
////
|
|
|
|
DLL void sim_set_data(struct Net** net_queue_in, int* num_net_queue_in, struct Gate** gate_queue_in, int* num_gate_queue_in, int* current_tick_in, int queue_max_in) {
|
|
net_queue = net_queue_in;
|
|
num_net_queue = num_net_queue_in;
|
|
gate_queue = gate_queue_in;
|
|
num_gate_queue = num_gate_queue_in;
|
|
current_tick = current_tick_in;
|
|
//queue_max = queue_max_in;
|
|
}
|
|
|
|
FAST void sim_update_net(const struct Net* const net);
|
|
DLL void sim_update_nets() {
|
|
for(int i=0; i<*num_net_queue; i++) {
|
|
struct Net* net = net_queue[i];
|
|
sim_update_net(net);
|
|
*(net->in_queue) = 0;
|
|
net_queue[i] = 0;
|
|
}
|
|
*num_net_queue = 0;
|
|
}
|
|
|
|
FAST void sim_dequeue_gate(const int i) {
|
|
gate_queue[i] = gate_queue[*num_gate_queue-1];
|
|
gate_queue[*num_gate_queue-1] = 0;
|
|
(*num_gate_queue)--;
|
|
}
|
|
DLL void sim_update_gates() {
|
|
for(int i=0; i<*num_gate_queue; i++) {
|
|
struct Gate* gate = gate_queue[i];
|
|
if(gate->logic_function != 0) {
|
|
sim_dequeue_gate(i);
|
|
*(gate->in_queue) = 0;
|
|
sim_logic_functions[gate->logic_function](gate);
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
|
|
////
|
|
|
|
FAST void sim_queue_gate(const struct Gate* const gate) {
|
|
//assert(*num_gate_queue < queue_max - 1);
|
|
*(gate->in_queue) = 1;
|
|
gate_queue[(*num_gate_queue)++] = (struct Gate*)gate;
|
|
}
|
|
|
|
FAST void sim_queue_net(const struct Net* const net) {
|
|
//assert(*num_net_queue < queue_max - 1);
|
|
*(net->in_queue) = 1;
|
|
net_queue[(*num_net_queue)++] = (struct Net*)net;
|
|
}
|
|
|
|
////
|
|
|
|
FAST void sim_update_net(const struct Net* const net) {
|
|
int state = *(net->state_num) > 0;
|
|
if(state != *(net->state)) {
|
|
*(net->state) = state;
|
|
*(net->update_tick) = *current_tick;
|
|
|
|
for(int i=0; i<*(net->num_gates_update); i++) {
|
|
struct Gate* gate = net->gates_update_c[i];
|
|
if(!*(gate->in_queue)) {
|
|
sim_queue_gate(gate);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
////
|
|
|
|
FAST int sim_gate_get_port(const struct Gate* const gate, const int port) {
|
|
return *(gate->port_net_state[port]);
|
|
}
|
|
FAST int sim_gate_get_port_rising(const struct Gate* const gate, const int port) {
|
|
return ( *(gate->port_net_state[port])) && ((*(gate->port_nets_c[port]->update_tick) == *current_tick));
|
|
}
|
|
FAST int sim_gate_get_port_falling(const struct Gate* const gate, const int port) {
|
|
return (!*(gate->port_net_state[port])) && ((*(gate->port_nets_c[port]->update_tick) == *current_tick));
|
|
}
|
|
FAST void sim_gate_set_port(const struct Gate* const gate, const int port, const int state) {
|
|
if(state != gate->port_states[port]) {
|
|
*(gate->port_net_state_num[port]) += state - gate->port_states[port];
|
|
gate->port_states[port] = state;
|
|
|
|
if(
|
|
( (*(gate->port_net_state_num[port]) > 0) != *(gate->port_net_state[port]) ) &&
|
|
( !*(gate->port_net_in_queue[port]) )
|
|
) {
|
|
sim_queue_net(gate->port_nets_c[port]);
|
|
}
|
|
}
|
|
}
|
|
FAST int sim_gate_get_data(const struct Gate* const gate, const int addr) {
|
|
//assert(addr>=0 && addr<gate->data_size);
|
|
return gate->data[addr];
|
|
}
|
|
FAST void sim_gate_set_data(const struct Gate* const gate, const int addr, const int val) {
|
|
//assert(addr>=0 && addr<gate->data_size);
|
|
gate->data[addr] = val;
|
|
}
|
|
FAST unsigned int sim_gate_get_word(const struct Gate* const gate, const int size, const int idx) {
|
|
int val = 0;
|
|
for(int i=0; i<size; i++) {
|
|
val += sim_gate_get_port(gate, idx+i) << i;
|
|
}
|
|
return val;
|
|
}
|
|
FAST void sim_gate_set_word(const struct Gate* const gate, const int size, const int idx, const unsigned int val) {
|
|
for(int i=0; i<size; i++) {
|
|
sim_gate_set_port(gate, idx+i, (val>>i) & 1);
|
|
}
|
|
}
|
|
FAST void sim_gate_set_word_64(const struct Gate* const gate, const int size, const int idx, const unsigned long long val) {
|
|
for(int i=0; i<size; i++) {
|
|
sim_gate_set_port(gate, idx+i, (val>>(unsigned long long)i) & 1ull);
|
|
}
|
|
}
|
|
|
|
////
|
|
|
|
#define GATEFUNCID(name) GateFunc_##name##_F
|
|
#define GATEFUNC(name) static GATEFUNCTYPE void GATEFUNCID(name)(const struct Gate* const gate)
|
|
#define setport(i, v) sim_gate_set_port(gate, i, v)
|
|
#define getport(i) sim_gate_get_port(gate, i)
|
|
#define setdata(i, v) sim_gate_set_data(gate, i, v)
|
|
#define getdata(i) sim_gate_get_data(gate, i)
|
|
#define getportrising(i) sim_gate_get_port_rising(gate, i)
|
|
#define getportfalling(i) sim_gate_get_port_falling(gate, i)
|
|
#define copyword(size, iin, iout) for(int i=0;i<size;i++) { setport(iout+i, getport(iin+i)); }
|
|
#define getword(size, idx) sim_gate_get_word(gate, size, idx)
|
|
#define clearword(size, idx) for(int i=0;i<size;i++) { setport(idx+i, 0); }
|
|
#define setword(size, idx, val) sim_gate_set_word(gate, size, idx, val)
|
|
#define setword64(size, idx, val) sim_gate_set_word_64(gate, size, idx, val)
|
|
|
|
#include "compiled_sim_gates.c"
|