arch-riscv,dev: Update the PLIC implementation (#886)
Update the PLIC based on the [riscv-plic-spec](https://github.com/riscv/riscv-plic-spec) in the PR: - Support customized PLIC hardID and privilege mode configuration - Backward compatable with the n_contexts parameter, will generate the config like {0,M}, {0,S}, {1,M} ... Change-Id: Ibff736827edb7c97921e01fa27f503574a27a562
This commit is contained in:
@@ -221,10 +221,10 @@ class HiFive(HiFiveBase):
|
|||||||
self.plic.n_src = max(plic_srcs) + 1
|
self.plic.n_src = max(plic_srcs) + 1
|
||||||
|
|
||||||
def setNumCores(self, num_cpu):
|
def setNumCores(self, num_cpu):
|
||||||
"""Sets the PLIC and CLINT to have the right number of threads and
|
"""Sets the CLINT to number of threads and the PLIC hartID/pmode for
|
||||||
contexts. Assumes that the cores have a single hardware thread.
|
each contexts. Assumes that the cores have a single hardware thread.
|
||||||
"""
|
"""
|
||||||
self.plic.n_contexts = num_cpu * 2
|
self.plic.hart_config = ",".join(["MS" for _ in range(num_cpu)])
|
||||||
self.clint.num_threads = num_cpu
|
self.clint.num_threads = num_cpu
|
||||||
|
|
||||||
def generateDeviceTree(self, state):
|
def generateDeviceTree(self, state):
|
||||||
|
|||||||
@@ -58,10 +58,8 @@ class PlicBase(BasicPioDevice):
|
|||||||
class Plic(PlicBase):
|
class Plic(PlicBase):
|
||||||
"""
|
"""
|
||||||
This implementation of PLIC is based on
|
This implementation of PLIC is based on
|
||||||
the SiFive U54MC datasheet:
|
the riscv-plic-spec repository:
|
||||||
https://sifive.cdn.prismic.io/sifive/fab000f6-
|
https://github.com/riscv/riscv-plic-spec/releases/tag/1.0.0
|
||||||
0e07-48d0-9602-e437d5367806_sifive_U54MC_rtl_
|
|
||||||
full_20G1.03.00_manual.pdf
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type = "Plic"
|
type = "Plic"
|
||||||
@@ -69,9 +67,20 @@ class Plic(PlicBase):
|
|||||||
cxx_class = "gem5::Plic"
|
cxx_class = "gem5::Plic"
|
||||||
pio_size = 0x4000000
|
pio_size = 0x4000000
|
||||||
n_src = Param.Int("Number of interrupt sources")
|
n_src = Param.Int("Number of interrupt sources")
|
||||||
|
# Ref: https://github.com/qemu/qemu/blob/760b4dc/hw/intc/sifive_plic.c#L285
|
||||||
|
hart_config = Param.String(
|
||||||
|
"",
|
||||||
|
"String represent for PLIC hart/pmode config like QEMU plic"
|
||||||
|
"Ex."
|
||||||
|
"'M' 1 hart with M mode"
|
||||||
|
"'MS,MS' 2 harts, 0-1 with M and S mode"
|
||||||
|
"'M,MS,MS,MS,MS' 5 harts, 0 with M mode, 1-5 with M and S mode",
|
||||||
|
)
|
||||||
n_contexts = Param.Int(
|
n_contexts = Param.Int(
|
||||||
|
0,
|
||||||
|
"Deprecated, use `hart_config` instead. "
|
||||||
"Number of interrupt contexts. Usually the number "
|
"Number of interrupt contexts. Usually the number "
|
||||||
"of threads * 2. One for M mode, one for S mode"
|
"of threads * 2. One for M mode, one for S mode",
|
||||||
)
|
)
|
||||||
|
|
||||||
def generateDeviceTree(self, state):
|
def generateDeviceTree(self, state):
|
||||||
@@ -89,12 +98,26 @@ class Plic(PlicBase):
|
|||||||
|
|
||||||
cpus = self.system.unproxy(self).cpu
|
cpus = self.system.unproxy(self).cpu
|
||||||
int_extended = list()
|
int_extended = list()
|
||||||
for cpu in cpus:
|
if self.n_contexts != 0:
|
||||||
phandle = int_state.phandle(cpu)
|
for cpu in cpus:
|
||||||
int_extended.append(phandle)
|
phandle = int_state.phandle(cpu)
|
||||||
int_extended.append(0xB)
|
int_extended.append(phandle)
|
||||||
int_extended.append(phandle)
|
int_extended.append(0xB)
|
||||||
int_extended.append(0x9)
|
int_extended.append(phandle)
|
||||||
|
int_extended.append(0x9)
|
||||||
|
elif self.hart_config != "":
|
||||||
|
cpu_id = 0
|
||||||
|
phandle = int_state.phandle(cpus[cpu_id])
|
||||||
|
for c in self.hart_config:
|
||||||
|
if c == ",":
|
||||||
|
cpu_id += 1
|
||||||
|
phandle = int_state.phandle(cpus[cpu_id])
|
||||||
|
elif c == "S":
|
||||||
|
int_extended.append(phandle)
|
||||||
|
int_extended.append(0x9)
|
||||||
|
elif c == "M":
|
||||||
|
int_extended.append(phandle)
|
||||||
|
int_extended.append(0xB)
|
||||||
|
|
||||||
node.append(FdtPropertyWords("interrupts-extended", int_extended))
|
node.append(FdtPropertyWords("interrupts-extended", int_extended))
|
||||||
node.append(FdtProperty("interrupt-controller"))
|
node.append(FdtProperty("interrupt-controller"))
|
||||||
|
|||||||
@@ -57,10 +57,18 @@ Plic::Plic(const Params ¶ms) :
|
|||||||
PlicBase(params),
|
PlicBase(params),
|
||||||
system(params.system),
|
system(params.system),
|
||||||
nSrc(params.n_src),
|
nSrc(params.n_src),
|
||||||
nContext(params.n_contexts),
|
|
||||||
registers(params.name, pioAddr, this),
|
registers(params.name, pioAddr, this),
|
||||||
update([this]{updateOutput();}, name() + ".update")
|
update([this]{updateOutput();}, name() + ".update")
|
||||||
{
|
{
|
||||||
|
fatal_if(params.hart_config != "" && params.n_contexts != 0,
|
||||||
|
"the hart_config and n_contexts can't be set simultaneously");
|
||||||
|
|
||||||
|
if (params.n_contexts != 0) {
|
||||||
|
initContextFromNContexts(params.n_contexts);
|
||||||
|
}
|
||||||
|
if (params.hart_config != "") {
|
||||||
|
initContextFromHartConfig(params.hart_config);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -80,7 +88,7 @@ Plic::post(int src_id)
|
|||||||
|
|
||||||
// Update states
|
// Update states
|
||||||
pendingPriority[src_id] = registers.priority[src_id].get();
|
pendingPriority[src_id] = registers.priority[src_id].get();
|
||||||
for (int i = 0; i < nContext; i++) {
|
for (int i = 0; i < contextConfigs.size(); i++) {
|
||||||
bool enabled = bits(registers.enable[i][src_index].get(), src_offset);
|
bool enabled = bits(registers.enable[i][src_index].get(), src_offset);
|
||||||
effPriority[i][src_id] = enabled ? pendingPriority[src_id] : 0;
|
effPriority[i][src_id] = enabled ? pendingPriority[src_id] : 0;
|
||||||
}
|
}
|
||||||
@@ -109,7 +117,7 @@ Plic::clear(int src_id)
|
|||||||
|
|
||||||
// Update states
|
// Update states
|
||||||
pendingPriority[src_id] = 0;
|
pendingPriority[src_id] = 0;
|
||||||
for (int i = 0; i < nContext; i++) {
|
for (int i = 0; i < contextConfigs.size(); i++) {
|
||||||
effPriority[i][src_id] = 0;
|
effPriority[i][src_id] = 0;
|
||||||
}
|
}
|
||||||
DPRINTF(Plic,
|
DPRINTF(Plic,
|
||||||
@@ -174,20 +182,20 @@ Plic::init()
|
|||||||
|
|
||||||
// Setup internal states
|
// Setup internal states
|
||||||
pendingPriority.resize(nSrc, 0x0);
|
pendingPriority.resize(nSrc, 0x0);
|
||||||
for (int i = 0; i < nContext; i++) {
|
for (int i = 0; i < contextConfigs.size(); i++) {
|
||||||
std::vector<uint32_t> context_priority(nSrc, 0x0);
|
std::vector<uint32_t> context_priority(nSrc, 0x0);
|
||||||
effPriority.push_back(context_priority);
|
effPriority.push_back(context_priority);
|
||||||
}
|
}
|
||||||
lastID.resize(nContext, 0x0);
|
lastID.resize(contextConfigs.size(), 0x0);
|
||||||
|
|
||||||
// Setup outputs
|
// Setup outputs
|
||||||
output = PlicOutput{
|
output = PlicOutput{
|
||||||
std::vector<uint32_t>(nContext, 0x0),
|
std::vector<uint32_t>(contextConfigs.size(), 0x0),
|
||||||
std::vector<uint32_t>(nContext, 0x0)};
|
std::vector<uint32_t>(contextConfigs.size(), 0x0)};
|
||||||
|
|
||||||
DPRINTF(Plic,
|
DPRINTF(Plic,
|
||||||
"Device init - %d contexts, %d sources, %d pending registers\n",
|
"Device init - %d contexts, %d sources, %d pending registers\n",
|
||||||
nContext, nSrc, nSrc32);
|
contextConfigs.size(), nSrc, nSrc32);
|
||||||
|
|
||||||
BasicPioDevice::init();
|
BasicPioDevice::init();
|
||||||
}
|
}
|
||||||
@@ -204,15 +212,15 @@ Plic::PlicRegisters::init()
|
|||||||
- plic->nSrc32 * 4;
|
- plic->nSrc32 * 4;
|
||||||
reserved.emplace_back("reserved1", reserve1_size);
|
reserved.emplace_back("reserved1", reserve1_size);
|
||||||
const size_t reserve2_size = thresholdStart - enableStart
|
const size_t reserve2_size = thresholdStart - enableStart
|
||||||
- plic->nContext * enablePadding;
|
- plic->contextConfigs.size() * enablePadding;
|
||||||
reserved.emplace_back("reserved2", reserve2_size);
|
reserved.emplace_back("reserved2", reserve2_size);
|
||||||
const size_t reserve3_size = plic->pioSize - thresholdStart
|
const size_t reserve3_size = plic->pioSize - thresholdStart
|
||||||
- plic->nContext * thresholdPadding;
|
- plic->contextConfigs.size() * thresholdPadding;
|
||||||
reserved.emplace_back("reserved3", reserve3_size);
|
reserved.emplace_back("reserved3", reserve3_size);
|
||||||
|
|
||||||
// Sanity check
|
// Sanity check
|
||||||
assert(plic->pioSize >= thresholdStart
|
assert(plic->pioSize >= thresholdStart
|
||||||
+ plic->nContext * thresholdPadding);
|
+ plic->contextConfigs.size() * thresholdPadding);
|
||||||
assert((int) plic->pioSize <= maxBankSize);
|
assert((int) plic->pioSize <= maxBankSize);
|
||||||
|
|
||||||
// Calculate hole sizes
|
// Calculate hole sizes
|
||||||
@@ -228,7 +236,7 @@ Plic::PlicRegisters::init()
|
|||||||
pending.emplace_back(
|
pending.emplace_back(
|
||||||
std::string("pending") + std::to_string(i), 0);
|
std::string("pending") + std::to_string(i), 0);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < plic->nContext; i++) {
|
for (int i = 0; i < plic->contextConfigs.size(); i++) {
|
||||||
|
|
||||||
enable.push_back(std::vector<Register32>());
|
enable.push_back(std::vector<Register32>());
|
||||||
for (int j = 0; j < plic->nSrc32; j++) {
|
for (int j = 0; j < plic->nSrc32; j++) {
|
||||||
@@ -264,7 +272,7 @@ Plic::PlicRegisters::init()
|
|||||||
addRegister(reserved[1]);
|
addRegister(reserved[1]);
|
||||||
|
|
||||||
// Enable
|
// Enable
|
||||||
for (int i = 0; i < plic->nContext; i++) {
|
for (int i = 0; i < plic->contextConfigs.size(); i++) {
|
||||||
for (int j = 0; j < plic->nSrc32; j++) {
|
for (int j = 0; j < plic->nSrc32; j++) {
|
||||||
auto write_cb = std::bind(&Plic::writeEnable, plic, _1, _2, j, i);
|
auto write_cb = std::bind(&Plic::writeEnable, plic, _1, _2, j, i);
|
||||||
enable[i][j].writer(write_cb);
|
enable[i][j].writer(write_cb);
|
||||||
@@ -275,7 +283,7 @@ Plic::PlicRegisters::init()
|
|||||||
addRegister(reserved[2]);
|
addRegister(reserved[2]);
|
||||||
|
|
||||||
// Threshold and claim
|
// Threshold and claim
|
||||||
for (int i = 0; i < plic->nContext; i++) {
|
for (int i = 0; i < plic->contextConfigs.size(); i++) {
|
||||||
auto threshold_cb = std::bind(&Plic::writeThreshold, plic, _1, _2, i);
|
auto threshold_cb = std::bind(&Plic::writeThreshold, plic, _1, _2, i);
|
||||||
threshold[i].writer(threshold_cb);
|
threshold[i].writer(threshold_cb);
|
||||||
auto read_cb = std::bind(&Plic::readClaim, plic, _1, i);
|
auto read_cb = std::bind(&Plic::readClaim, plic, _1, i);
|
||||||
@@ -301,7 +309,7 @@ Plic::writePriority(Register32& reg, const uint32_t& data, const int src_id)
|
|||||||
// Update states
|
// Update states
|
||||||
bool pending = bits(registers.pending[src_index].get(), src_offset);
|
bool pending = bits(registers.pending[src_index].get(), src_offset);
|
||||||
pendingPriority[src_id] = pending ? reg.get() : 0;
|
pendingPriority[src_id] = pending ? reg.get() : 0;
|
||||||
for (int i = 0; i < nContext; i++) {
|
for (int i = 0; i < contextConfigs.size(); i++) {
|
||||||
bool enabled = bits(
|
bool enabled = bits(
|
||||||
registers.enable[i][src_index].get(), src_offset);
|
registers.enable[i][src_index].get(), src_offset);
|
||||||
effPriority[i][src_id] = enabled ? pendingPriority[src_id] : 0;
|
effPriority[i][src_id] = enabled ? pendingPriority[src_id] : 0;
|
||||||
@@ -394,11 +402,11 @@ Plic::propagateOutput()
|
|||||||
{
|
{
|
||||||
// Calculate new output
|
// Calculate new output
|
||||||
PlicOutput new_output{
|
PlicOutput new_output{
|
||||||
std::vector<uint32_t>(nContext, 0x0),
|
std::vector<uint32_t>(contextConfigs.size(), 0x0),
|
||||||
std::vector<uint32_t>(nContext, 0x0)};
|
std::vector<uint32_t>(contextConfigs.size(), 0x0)};
|
||||||
uint32_t max_id;
|
uint32_t max_id;
|
||||||
uint32_t max_priority;
|
uint32_t max_priority;
|
||||||
for (int i = 0; i < nContext; i++) {
|
for (int i = 0; i < contextConfigs.size(); i++) {
|
||||||
max_id = max_element(effPriority[i].begin(),
|
max_id = max_element(effPriority[i].begin(),
|
||||||
effPriority[i].end()) - effPriority[i].begin();
|
effPriority[i].end()) - effPriority[i].begin();
|
||||||
max_priority = effPriority[i][max_id];
|
max_priority = effPriority[i][max_id];
|
||||||
@@ -421,6 +429,39 @@ Plic::propagateOutput()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Plic::initContextFromNContexts(int n_contexts)
|
||||||
|
{
|
||||||
|
contextConfigs.reserve(n_contexts);
|
||||||
|
for (uint32_t i = 0; i < (uint32_t)n_contexts; i += 2) {
|
||||||
|
contextConfigs.emplace_back((i >> 1), ExceptionCode::INT_EXT_MACHINE);
|
||||||
|
contextConfigs.emplace_back((i >> 1), ExceptionCode::INT_EXT_SUPER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Plic::initContextFromHartConfig(const std::string& hart_config)
|
||||||
|
{
|
||||||
|
contextConfigs.reserve(hart_config.size());
|
||||||
|
uint32_t hart_id = 0;
|
||||||
|
for (char c: hart_config) {
|
||||||
|
switch (c) {
|
||||||
|
case ',':
|
||||||
|
hart_id++;
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
contextConfigs.emplace_back(hart_id, ExceptionCode::INT_EXT_MACHINE);
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
contextConfigs.emplace_back(hart_id, ExceptionCode::INT_EXT_SUPER);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatal("hart_config should not contains the value: %c", c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Plic::updateOutput()
|
Plic::updateOutput()
|
||||||
{
|
{
|
||||||
@@ -443,10 +484,8 @@ void
|
|||||||
Plic::updateInt()
|
Plic::updateInt()
|
||||||
{
|
{
|
||||||
// Update xEIP lines
|
// Update xEIP lines
|
||||||
for (int i = 0; i < nContext; i++) {
|
for (int i = 0; i < contextConfigs.size(); i++) {
|
||||||
int thread_id = i >> 1;
|
auto [thread_id, int_id] = contextConfigs[i];
|
||||||
int int_id = (i & 1) ?
|
|
||||||
ExceptionCode::INT_EXT_SUPER : ExceptionCode::INT_EXT_MACHINE;
|
|
||||||
|
|
||||||
auto tc = system->threads[thread_id];
|
auto tc = system->threads[thread_id];
|
||||||
uint32_t max_id = output.maxID[i];
|
uint32_t max_id = output.maxID[i];
|
||||||
|
|||||||
@@ -57,11 +57,9 @@ namespace gem5
|
|||||||
using namespace RiscvISA;
|
using namespace RiscvISA;
|
||||||
/**
|
/**
|
||||||
* NOTE:
|
* NOTE:
|
||||||
* This implementation of CLINT is based on
|
* This implementation of PLIC is based on
|
||||||
* the SiFive U54MC datasheet:
|
* he riscv-plic-spec repository:
|
||||||
* https://sifive.cdn.prismic.io/sifive/fab000f6-
|
* https://github.com/riscv/riscv-plic-spec/releases/tag/1.0.0
|
||||||
* 0e07-48d0-9602-e437d5367806_sifive_U54MC_rtl_
|
|
||||||
* full_20G1.03.00_manual.pdf
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -124,13 +122,9 @@ class Plic : public PlicBase
|
|||||||
*/
|
*/
|
||||||
int nSrc32;
|
int nSrc32;
|
||||||
/**
|
/**
|
||||||
* Number of interrupt contexts
|
* PLIC hart/pmode address configs, stored in the format {hartID, pmode}
|
||||||
* = nThread * 2
|
|
||||||
* e.g. context 0 => thread 0 M mode
|
|
||||||
* context 1 => thread 0 S mode
|
|
||||||
* This is based on SiFive U54MC datasheet
|
|
||||||
*/
|
*/
|
||||||
int nContext;
|
std::vector<std::pair<uint32_t, ExceptionCode>> contextConfigs;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef PlicParams Params;
|
typedef PlicParams Params;
|
||||||
@@ -261,6 +255,12 @@ class Plic : public PlicBase
|
|||||||
std::vector<uint32_t> lastID;
|
std::vector<uint32_t> lastID;
|
||||||
PlicOutput output;
|
PlicOutput output;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function for handling context config from params
|
||||||
|
*/
|
||||||
|
void initContextFromNContexts(int n_contexts);
|
||||||
|
void initContextFromHartConfig(const std::string& hart_config);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trigger:
|
* Trigger:
|
||||||
* - Plic::post
|
* - Plic::post
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ class LupvBoard(AbstractSystemBoard, KernelDiskWorkload):
|
|||||||
# point for our bbl to use upon startup, and will
|
# point for our bbl to use upon startup, and will
|
||||||
# remain unused during the simulation
|
# remain unused during the simulation
|
||||||
self.pic.n_src = 0
|
self.pic.n_src = 0
|
||||||
self.pic.n_contexts = 0
|
self.pic.hart_config = ""
|
||||||
self.lupio_pic.n_src = max(pic_srcs) + 1
|
self.lupio_pic.n_src = max(pic_srcs) + 1
|
||||||
self.lupio_pic.num_threads = self.processor.get_num_cores()
|
self.lupio_pic.num_threads = self.processor.get_num_cores()
|
||||||
|
|
||||||
@@ -403,10 +403,19 @@ class LupvBoard(AbstractSystemBoard, KernelDiskWorkload):
|
|||||||
plic_node.append(FdtPropertyWords("riscv,ndev", 0))
|
plic_node.append(FdtPropertyWords("riscv,ndev", 0))
|
||||||
|
|
||||||
int_extended = list()
|
int_extended = list()
|
||||||
for i, core in enumerate(self.get_processor().get_cores()):
|
cpu_id = 0
|
||||||
phandle = state.phandle(f"cpu@{i}.int_state")
|
phandle = int_state.phandle(f"cpu@{cpu_id}.int_state")
|
||||||
int_extended.append(phandle)
|
for c in plic.hart_config:
|
||||||
int_extended.append(self._excep_code["INT_EXT_MACHINE"])
|
if c == ",":
|
||||||
|
cpu_id += 1
|
||||||
|
assert cpu_id < self.get_processor().get_num_cores()
|
||||||
|
phandle = int_state.phandle(f"cpu@{cpu_id}.int_state")
|
||||||
|
elif c == "S":
|
||||||
|
int_extended.append(phandle)
|
||||||
|
int_extended.append(self._excep_code["INT_SOFT_SUPER"])
|
||||||
|
elif c == "M":
|
||||||
|
int_extended.append(phandle)
|
||||||
|
int_extended.append(self._excep_code["INT_EXT_MACHINE"])
|
||||||
|
|
||||||
plic_node.append(FdtPropertyWords("interrupts-extended", int_extended))
|
plic_node.append(FdtPropertyWords("interrupts-extended", int_extended))
|
||||||
plic_node.append(FdtProperty("interrupt-controller"))
|
plic_node.append(FdtProperty("interrupt-controller"))
|
||||||
|
|||||||
@@ -102,7 +102,9 @@ class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload):
|
|||||||
# Contains a CLINT, PLIC, UART, and some functions for the dtb, etc.
|
# Contains a CLINT, PLIC, UART, and some functions for the dtb, etc.
|
||||||
self.platform = HiFive()
|
self.platform = HiFive()
|
||||||
# Note: This only works with single threaded cores.
|
# Note: This only works with single threaded cores.
|
||||||
self.platform.plic.n_contexts = self.processor.get_num_cores() * 2
|
self.platform.plic.hart_config = ",".join(
|
||||||
|
["MS" for _ in range(self.processor.get_num_cores())]
|
||||||
|
)
|
||||||
self.platform.attachPlic()
|
self.platform.attachPlic()
|
||||||
self.platform.clint.num_threads = self.processor.get_num_cores()
|
self.platform.clint.num_threads = self.processor.get_num_cores()
|
||||||
|
|
||||||
@@ -353,12 +355,19 @@ class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload):
|
|||||||
plic_node.append(FdtPropertyWords("riscv,ndev", [plic.n_src - 1]))
|
plic_node.append(FdtPropertyWords("riscv,ndev", [plic.n_src - 1]))
|
||||||
|
|
||||||
int_extended = list()
|
int_extended = list()
|
||||||
for i, core in enumerate(self.get_processor().get_cores()):
|
cpu_id = 0
|
||||||
phandle = state.phandle(f"cpu@{i}.int_state")
|
phandle = int_state.phandle(f"cpu@{cpu_id}.int_state")
|
||||||
int_extended.append(phandle)
|
for c in plic.hart_config:
|
||||||
int_extended.append(0xB)
|
if c == ",":
|
||||||
int_extended.append(phandle)
|
cpu_id += 1
|
||||||
int_extended.append(0x9)
|
assert cpu_id < self.get_processor().get_num_cores()
|
||||||
|
phandle = int_state.phandle(f"cpu@{cpu_id}.int_state")
|
||||||
|
elif c == "S":
|
||||||
|
int_extended.append(phandle)
|
||||||
|
int_extended.append(0x9)
|
||||||
|
elif c == "M":
|
||||||
|
int_extended.append(phandle)
|
||||||
|
int_extended.append(0xB)
|
||||||
|
|
||||||
plic_node.append(FdtPropertyWords("interrupts-extended", int_extended))
|
plic_node.append(FdtPropertyWords("interrupts-extended", int_extended))
|
||||||
plic_node.append(FdtProperty("interrupt-controller"))
|
plic_node.append(FdtProperty("interrupt-controller"))
|
||||||
|
|||||||
@@ -149,7 +149,9 @@ class RISCVMatchedBoard(
|
|||||||
# Contains a CLINT, PLIC, UART, and some functions for the dtb, etc.
|
# Contains a CLINT, PLIC, UART, and some functions for the dtb, etc.
|
||||||
self.platform = HiFive()
|
self.platform = HiFive()
|
||||||
# Note: This only works with single threaded cores.
|
# Note: This only works with single threaded cores.
|
||||||
self.platform.plic.n_contexts = self.processor.get_num_cores() * 2
|
self.platform.plic.hart_config = ",".join(
|
||||||
|
["MS" for _ in range(self.processor.get_num_cores())]
|
||||||
|
)
|
||||||
self.platform.attachPlic()
|
self.platform.attachPlic()
|
||||||
self.platform.clint.num_threads = self.processor.get_num_cores()
|
self.platform.clint.num_threads = self.processor.get_num_cores()
|
||||||
|
|
||||||
@@ -433,12 +435,19 @@ class RISCVMatchedBoard(
|
|||||||
plic_node.append(FdtPropertyWords("riscv,ndev", [plic.n_src - 1]))
|
plic_node.append(FdtPropertyWords("riscv,ndev", [plic.n_src - 1]))
|
||||||
|
|
||||||
int_extended = list()
|
int_extended = list()
|
||||||
for i, core in enumerate(self.get_processor().get_cores()):
|
cpu_id = 0
|
||||||
phandle = state.phandle(f"cpu@{i}.int_state")
|
phandle = int_state.phandle(f"cpu@{cpu_id}.int_state")
|
||||||
int_extended.append(phandle)
|
for c in plic.hart_config:
|
||||||
int_extended.append(0xB)
|
if c == ",":
|
||||||
int_extended.append(phandle)
|
cpu_id += 1
|
||||||
int_extended.append(0x9)
|
assert cpu_id < self.get_processor().get_num_cores()
|
||||||
|
phandle = int_state.phandle(f"cpu@{cpu_id}.int_state")
|
||||||
|
elif c == "S":
|
||||||
|
int_extended.append(phandle)
|
||||||
|
int_extended.append(0x9)
|
||||||
|
elif c == "M":
|
||||||
|
int_extended.append(phandle)
|
||||||
|
int_extended.append(0xB)
|
||||||
|
|
||||||
plic_node.append(FdtPropertyWords("interrupts-extended", int_extended))
|
plic_node.append(FdtPropertyWords("interrupts-extended", int_extended))
|
||||||
plic_node.append(FdtProperty("interrupt-controller"))
|
plic_node.append(FdtProperty("interrupt-controller"))
|
||||||
|
|||||||
Reference in New Issue
Block a user