wait_for_packet();
}
-void htif_t::wait_for_tohost_write()
-{
- while(wait_for_packet() != APP_CMD_READ_CONTROL_REG);
-}
-
-void htif_t::wait_for_fromhost_write()
-{
- while(wait_for_packet() != APP_CMD_WRITE_CONTROL_REG);
-}
-
void htif_t::send_packet(packet* p)
{
size_t data_size = p->data_size*HTIF_DATA_ALIGN;
send_packet(&p);
}
-void htif_t::poll()
-{
- struct pollfd pfd;
- pfd.fd = fromhost_fd;
- pfd.events = POLLIN;
- pfd.revents = 0;
-
- if (::poll(&pfd, 1, 0) > 0)
- wait_for_packet();
-}
-
int htif_t::wait_for_packet()
{
while(1)
}
packet ackpacket = {APP_CMD_ACK,0,seqno,0};
+ reg_t pcr_coreid = p.addr >> 20;
+ reg_t pcr_reg = p.addr & ((1<<20)-1);
switch(p.cmd)
{
sim->mmu->store_uint64((p.addr+i)*HTIF_DATA_ALIGN, p.data[i]);
break;
case APP_CMD_READ_CONTROL_REG:
- assert(p.addr == PCR_TOHOST);
+ {
+ assert(pcr_coreid < sim->num_cores());
assert(p.data_size == 1);
ackpacket.data_size = 1;
- memcpy(ackpacket.data, &sim->tohost, sizeof(reg_t));
+ reg_t pcr = sim->procs[pcr_coreid]->get_pcr(pcr_reg);
+ memcpy(ackpacket.data, &pcr, sizeof(pcr));
break;
+ }
case APP_CMD_WRITE_CONTROL_REG:
- assert(p.addr == PCR_FROMHOST || p.addr == PCR_RESET);
+ assert(pcr_coreid < sim->num_cores());
assert(p.data_size == 1);
- sim->tohost = 0;
- if (p.addr == PCR_FROMHOST)
- memcpy(&sim->fromhost, p.data, sizeof(reg_t));
- else if (p.addr == PCR_RESET)
+ if (pcr_reg == PCR_RESET)
+ {
+ if (p.data[0] & 1)
+ {
+ sim->procs[pcr_coreid]->reset();
+ if (pcr_coreid == 0 && sim->procs[0]->running())
+ sim->stop();
+ }
+ else if (!sim->procs[pcr_coreid]->running())
+ {
+ reset = false;
+ sim->procs[pcr_coreid]->deliver_ipi();
+ }
+ }
+ else
{
- bool next_reset = p.data[0] & 1;
- if (!reset && next_reset)
- sim->stop();
- reset = next_reset;
+ reg_t pcr;
+ memcpy(&pcr, p.data, sizeof(pcr));
+ sim->procs[pcr_coreid]->set_pcr(pcr_reg, pcr);
}
break;
}
~htif_t();
void init(sim_t* _sim);
- // wait for host to send start command
void wait_for_start();
-
- // we block on the host if the target machine reads the fromhost register,
- // which provides determinism in tohost/fromhost communication.
- void wait_for_tohost_write();
- void wait_for_fromhost_write();
-
- // check to see if there's a pending packet and process it if so
- void poll();
+ int wait_for_packet();
private:
sim_t* sim;
void nack(uint8_t seqno);
void send_packet(packet* p);
- int wait_for_packet();
};
#endif
#include "config.h"
#include "sim.h"
#include "disasm.h"
+#include <inttypes.h>
#include <cmath>
#include <cstdlib>
#include <iostream>
void processor_t::take_trap(reg_t t, bool noisy)
{
if(noisy)
- printf("core %3d: trap %s, pc 0x%016llx\n",
- id, trap_name(trap_t(t)), (unsigned long long)pc);
+ {
+ if ((sreg_t)t < 0)
+ printf("core %3d: interrupt %lld, pc 0x%016llx\n",
+ id, (long long)(t << 1 >> 1), (unsigned long long)pc);
+ else
+ printf("core %3d: trap %s, pc 0x%016llx\n",
+ id, trap_name(trap_t(t)), (unsigned long long)pc);
+ }
// switch to supervisor, set previous supervisor bit, disable traps
set_pcr(PCR_SR, (((sr & ~SR_ET) | SR_S) & ~SR_PS) | ((sr & SR_S) ? SR_PS : 0));
void processor_t::deliver_ipi()
{
- interrupts_pending |= 1 << IRQ_IPI;
+ set_pcr(PCR_CLR_IPI, 1);
run = true;
}
sim.send_ipi(val);
break;
case PCR_CLR_IPI:
- interrupts_pending &= ~(1 << IRQ_IPI);
+ if (val & 1)
+ interrupts_pending |= (1 << IRQ_IPI);
+ else
+ interrupts_pending &= ~(1 << IRQ_IPI);
break;
case PCR_K0:
pcr_k0 = val;
vecbanks_count = __builtin_popcountll(vecbanks);
break;
case PCR_TOHOST:
- sim.set_tohost(val);
+ fromhost = 0;
+ tohost = val;
+ break;
+ case PCR_FROMHOST:
+ fromhost = val;
+ tohost = 0;
break;
}
}
case PCR_VECBANK:
return vecbanks;
case PCR_TOHOST:
- return sim.get_tohost();
+ return tohost;
case PCR_FROMHOST:
- return sim.get_fromhost();
+ return fromhost;
}
return -1;
}
processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id);
~processor_t();
+ void reset();
void step(size_t n, bool noisy); // run for n cycles
void deliver_ipi(); // register an interprocessor interrupt
+ bool running() { return run; }
+ void set_pcr(int which, reg_t val);
+ reg_t get_pcr(int which);
private:
sim_t& sim;
reg_t pcr_k0;
reg_t pcr_k1;
reg_t cause;
+ reg_t tohost;
+ reg_t fromhost;
uint32_t interrupts_pending;
uint32_t id;
uint32_t sr; // only modify the status register using set_pcr()
bool run;
// functions
- void reset(); // resets architected state; halts processor if it was running
void take_interrupt(); // take a trap if any interrupts are pending
- void set_pcr(int which, reg_t val);
- reg_t get_pcr(int which);
void set_fsr(uint32_t val); // set the floating-point status register
void take_trap(reg_t t, bool noisy); // take an exception
void disasm(insn_t insn, reg_t pc); // disassemble and print an instruction
munmap(mem, memsz);
}
-void sim_t::set_tohost(reg_t val)
-{
- fromhost = 0;
- tohost = val;
- htif->wait_for_tohost_write();
-}
-
-reg_t sim_t::get_tohost()
-{
- return tohost;
-}
-
-reg_t sim_t::get_fromhost()
-{
- htif->wait_for_fromhost_write();
- return fromhost;
-}
-
void sim_t::send_ipi(reg_t who)
{
if(who < num_cores())
void sim_t::run(bool debug)
{
- htif->wait_for_start();
-
// word 0 of memory contains the memory capacity in MB
mmu->store_uint32(0, memsz >> 20);
// word 1 of memory contains the core count
mmu->store_uint32(4, num_cores());
- // start core 0
- send_ipi(0);
+ //htif->wait_for_start();
for(running = true; running; )
{
- for (int i = 0; i < 1000; i++)
- {
- if(!debug)
- step_all(100,100,false);
- else
- interactive();
- }
-
- htif->poll();
+ if(!debug)
+ step_all(10000, 100, false);
+ else
+ interactive();
}
}
void sim_t::step_all(size_t n, size_t interleave, bool noisy)
{
+ htif->wait_for_packet();
for(size_t j = 0; j < n; j+=interleave)
for(int i = 0; i < (int)num_cores(); i++)
procs[i]->step(interleave,noisy);
// run the simulation to completion
void run(bool debug);
- // communicate with the host machine
- void set_tohost(reg_t val);
- reg_t get_tohost();
- reg_t get_fromhost();
-
// deliver an IPI to a specific processor
void send_ipi(reg_t who);