Spike, a RISC-V ISA Simulator
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

99 lines
3.0 KiB

#include "led-device.h"
#include <cstring>
#include <cstdio>
#include <sstream>
#include <algorithm>
led_device_t::led_device_t(const sim_t *sim, reg_t base, size_t size, uint32_t num_leds)
: sim(sim), base_addr(base), dev_size(size),
num_leds(std::min(num_leds, 32u)), led_state(0) {
printf("LED device init at 0x%lx, size: 0x%lx, num_leds: %u\n",
base_addr, dev_size, this->num_leds);
}
bool led_device_t::load(reg_t addr, size_t len, uint8_t* bytes) {
printf("led_device_t::load from address: 0x%lx, length: %zu\n",
base_addr + addr, len);
if (addr == 0 && len == 4) {
uint32_t masked_state = led_state & ((1u << num_leds) - 1);
memcpy(bytes, &masked_state, 4);
return true;
}
return false;
}
bool led_device_t::store(reg_t addr, size_t len, const uint8_t* bytes) {
printf("led_device_t::store to address: 0x%lx, length: %zu\n",
base_addr + addr, len);
if (addr == 0 && len == 4) {
uint32_t new_state;
memcpy(&new_state, bytes, 4);
led_state = new_state & ((1u << num_leds) - 1);
printf("LED state changed to: 0x%x\n", led_state);
printf("LED pattern (%u LEDs): ", num_leds);
for (int i = num_leds - 1; i >= 0; i--) {
printf("%c", (led_state & (1 << i)) ? ' ' : '-');
}
printf(" (0x%x)\n", led_state);
return true;
}
return false;
}
size_t led_device_t::size() {
return dev_size;
}
led_device_t* led_parse_from_fdt(const void *fdt, const sim_t *sim,
reg_t *base, std::vector<std::string> args) {
if (args.size() < 3) {
fprintf(stderr, "Error: led device requires 3 arguments (base, size, num_leds)\n");
return nullptr;
}
try {
*base = std::stoull(args[0], nullptr, 0);
reg_t size = std::stoull(args[1], nullptr, 0);
uint32_t num_leds = std::stoul(args[2], nullptr, 0);
if (num_leds == 0 || num_leds > 32) {
fprintf(stderr, "Error: num_leds must be between 1 and 32, got %u\n", num_leds);
return nullptr;
}
return new led_device_t(sim, *base, size, num_leds);
} catch (const std::exception& e) {
fprintf(stderr, "Error parsing LED device params: %s\n", e.what());
return nullptr;
}
}
std::string led_generate_dts(const sim_t *sim, const std::vector<std::string> &args) {
std::ostringstream s;
reg_t base = 0x10001000;
reg_t size = 0x1000;
uint32_t num_leds = 8;
if (args.size() >= 3) {
base = std::stoull(args[0], nullptr, 0);
size = std::stoull(args[1], nullptr, 0);
num_leds = std::stoul(args[2], nullptr, 0);
}
s << std::hex
<< " led@" << base << " {\n"
<< " compatible = \"led\";\n"
<< " reg = <0x0 0x" << base << " 0x0 0x" << size << ">;\n"
<< std::dec
<< " num-leds = <" << num_leds << ">;\n"
<< std::hex
<< " spike,plugin-params = \"0x" << base << ",0x" << size << "," << std::dec << num_leds << "\";\n"
<< " };\n";
return s.str();
}
REGISTER_DEVICE(led_device, led_parse_from_fdt, led_generate_dts)