-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmodel_dependent.cpp
More file actions
152 lines (132 loc) · 5.83 KB
/
Copy pathmodel_dependent.cpp
File metadata and controls
152 lines (132 loc) · 5.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
Backing storage for model_dependent.h's fake registers, and the
desktop-native reimplementations of pic32mx.c's chip-control functions
(delays, system reset, flash). These replace the real pic32mx.c body --
it contains inline MIPS assembly and CP0 cycle counting that simply
cannot compile on a desktop CPU, so rather than fake the silicon
underneath it, we give the same function signatures new bodies.
*/
#include "model_dependent.h"
#include "pic32mx.h"
#include <cstdio>
#include <cstring>
#include <ctime>
#include <cstdlib>
#include <chrono>
#include <thread>
/* ---------- GPIO backing storage --------------------------------------- */
volatile uint32_t REG_ANSEL[NUM_GPIO_PORTS] = {0};
volatile uint32_t REG_TRIS [NUM_GPIO_PORTS] = {0};
volatile uint32_t REG_LAT [NUM_GPIO_PORTS] = {0};
volatile uint32_t REG_ODC [NUM_GPIO_PORTS] = {0};
volatile uint32_t REG_CNPU [NUM_GPIO_PORTS] = {0};
volatile uint32_t REG_CNPD [NUM_GPIO_PORTS] = {0};
volatile uint32_t FAKE_RPxnR[NUM_GPIO_PORTS][16] = {{0}};
#define BANK(name, target_array) \
name[NUM_GPIO_PORTS] = { \
{&target_array[0]}, {&target_array[1]}, {&target_array[2]}, \
{&target_array[3]}, {&target_array[4]}, {&target_array[5]}, \
{&target_array[6]} }
RegSet BANK(PROXY_ANSELSET, REG_ANSEL);
RegClr BANK(PROXY_ANSELCLR, REG_ANSEL);
RegSet BANK(PROXY_TRISSET, REG_TRIS);
RegClr BANK(PROXY_TRISCLR, REG_TRIS);
RegSet BANK(PROXY_LATSET, REG_LAT);
RegClr BANK(PROXY_LATCLR, REG_LAT);
RegSet BANK(PROXY_ODCSET, REG_ODC);
RegClr BANK(PROXY_ODCCLR, REG_ODC);
RegSet BANK(PROXY_CNPUSET, REG_CNPU);
RegClr BANK(PROXY_CNPUCLR, REG_CNPU);
RegSet BANK(PROXY_CNPDSET, REG_CNPD);
RegClr BANK(PROXY_CNPDCLR, REG_CNPD);
#undef BANK
/* ---------- UART backing storage --------------------------------------- */
volatile uint32_t REG_UMODE[NUM_UART_UNIT] = {0};
volatile uint32_t REG_USTA [NUM_UART_UNIT] = {_U1STA_TRMT_MASK}; // start "idle/done"
volatile uint32_t REG_UBRG [NUM_UART_UNIT] = {0};
volatile uint32_t REG_URXREG[NUM_UART_UNIT] = {0};
volatile uint32_t FAKE_URXR[NUM_UART_UNIT] = {0};
RegSet PROXY_UMODESET[NUM_UART_UNIT] = { {®_UMODE[0]}, {®_UMODE[1]} };
RegClr PROXY_UMODECLR[NUM_UART_UNIT] = { {®_UMODE[0]}, {®_UMODE[1]} };
RegSet PROXY_USTASET [NUM_UART_UNIT] = { {®_USTA[0]}, {®_USTA[1]} };
RegClr PROXY_USTACLR [NUM_UART_UNIT] = { {®_USTA[0]}, {®_USTA[1]} };
TxRegProxy PROXY_UTXREG[NUM_UART_UNIT] = { {0}, {1} };
static void (*g_uart_tx_hook)(int unit, uint8_t byte) = nullptr;
void pic32emu_uart_set_tx_hook(void (*hook)(int unit, uint8_t byte)) {
g_uart_tx_hook = hook;
}
// Default behaviour if no test-harness hook is registered: print it.
static void default_tx_hook(int unit, uint8_t byte) {
printf("\033[96m[UART%d TX]\033[0m 0x%02X '%c'\n",
unit + 1, byte, (byte >= 32 && byte < 127) ? byte : '.');
}
TxRegProxy &TxRegProxy::operator=(uint32_t byte) {
// Real hardware: shift register drains the FIFO over time. On a
// desktop there's no real timing to model, so the byte is "sent"
// immediately and the busy/done status bits never need to go busy.
if (g_uart_tx_hook) g_uart_tx_hook(unit, (uint8_t)byte);
else default_tx_hook(unit, (uint8_t)byte);
return *this;
}
/* ---------- fake flash -------------------------------------------------- */
uint8_t FAKE_FLASH[FAKE_FLASH_SIZE];
unsigned int NVMUnlock(unsigned int /*nvmop*/) {
return 0; // desktop: never fails
}
unsigned int flash_erase_page(void *address) {
uintptr_t off = (uintptr_t)address - FLASH_SAVE_ADDR;
if (off >= FAKE_FLASH_SIZE) {
printf("\033[91m[FLASH FAULT] erase address out of range\033[0m\n");
return 1;
}
memset(FAKE_FLASH + off, 0xFF, FLASH_PAGE_SIZE); // erased flash reads as 0xFF
printf("\033[93m[FLASH]\033[0m erased page at offset 0x%04zx\n", (size_t)off);
return 0;
}
unsigned int flash_write_row(void *address, void *data) {
uintptr_t off = (uintptr_t)address - FLASH_SAVE_ADDR;
if (off >= FAKE_FLASH_SIZE) {
printf("\033[91m[FLASH FAULT] write address out of range\033[0m\n");
return 1;
}
memcpy(FAKE_FLASH + off, data, FLASH_ROW_SIZE);
printf("\033[93m[FLASH]\033[0m wrote row at offset 0x%04zx\n", (size_t)off);
return 0;
}
/* ---------- delays ------------------------------------------------------ */
void __delay_us(uint32_t us) {
std::this_thread::sleep_for(std::chrono::microseconds(us));
}
void __delay_ms(uint32_t ms) {
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}
/* ---------- system control ---------------------------------------------- */
void system_register_lock(void) { /* no-op: no protected SFRs to guard */ }
void system_register_unlock(void) { /* no-op: no protected SFRs to guard */ }
static void (*g_reset_hook)(void) = nullptr;
void pic32emu_register_reset_hook(void (*hook)(void)) { g_reset_hook = hook; }
void system_reset(void) {
printf("\033[91m[SIMULATED RESET]\033[0m chip would restart here.\n");
if (g_reset_hook) { g_reset_hook(); return; }
exit(0);
}
/* ---------- board-level stubs (no real onboard LEDs/switches on a laptop) */
void system_init(void) {
printf("\033[94m[EMU INIT]\033[0m Virtual PIC32MX170F256B platform ready.\n");
}
void onboard_led(int num, int on_off) {
printf("\033[93m[BOARD LED]\033[0m LED%d -> %s\n", num, on_off ? "ON" : "OFF");
}
int onboard_sw(int /*num*/) { return 0; }
/* ---------- debug helper ------------------------------------------------ */
void pic32emu_dump_gpio_state(void) {
static const char *names = "ABCDEFG";
printf("\n--- GPIO STATE ---\n");
for (int i = 0; i < NUM_GPIO_PORTS; i++) {
if (REG_TRIS[i] || REG_LAT[i] || REG_ANSEL[i]) {
printf("Port %c: TRIS=0x%04X LAT=0x%04X ANSEL=0x%04X\n",
names[i], REG_TRIS[i], REG_LAT[i], REG_ANSEL[i]);
}
}
printf("------------------\n");
}